1. Load required libraries
library(ALDEx2)
library(corpcor)
library(EnvStats)
library(gdata)
library(ggplot2)
library(gplots)
library(gridExtra)
library(growthcurver)
library(igraph)
library(multtest)
library(network)
library(plyr)
library(pheatmap)
library(RColorBrewer)
library(Rtsne)
library(viridis)

1.1 Load genome annotation related to efflux pumps, metabolism and transcriptional regulation (compiled from multiple sources)

#load transcriptional regulatory network compiled from RegulonDB (http://regulondb.ccg.unam.mx)
#rows are target genes and columns are regulators
#activation and repression are indicated with '1' and '-1', respectively
load("../Data/Input/Ecoli_TRN.RData")
#define transcription factor (TF) names
tf.names<-colnames(transcriptional.network)
#keep only locus tags for TF names (format is locus_name)
tf.names<-sapply(1:length(tf.names),function(x){strsplit(tf.names[x],split="_")[[1]][2]})
#read names of metabolic genes on the E. coli metabolic model iJO1366 (Orth et al. 2011, MSB)
metabolic.genes<-read.csv("../Data/Input/genes_metabolic_model_iJO1366.csv")
metabolic.genes<-metabolic.genes$Model.genes
#read efflux pump related genes (compiled from EcoCyc database and literature review)
effluxPump.genes<-read.csv("../Data/Input/efflux_pump_genes.csv",header=T)
effluxPump.genes<-effluxPump.genes$Locus
#exclude TFs and efflux pump related genes from the metabolic category
metabolic.genes<-setdiff(metabolic.genes,union(tf.names,effluxPump.genes))
#create function to convert locus tag to standard gene name (e.g., b0001 to thrL)
ecoli.trn.genes<-rownames(transcriptional.network)
convert.locus.to.gene.name<-function(locus.list)
{
  output<-sapply(1:length(locus.list),function(x){strsplit(ecoli.trn.genes[grep(locus.list[x],ecoli.trn.genes)],split="_")[[1]][1]})
  output
}

1.2 Run differential expression analysis of transcriptional data reported by Handel et al. (2014)

#perform differential expression analysis with a Bayesian t-test using Cyber-T algorithm (Baldi and Long, 2001)
#code downloaded from http://cybert.ics.uci.edu
source("Bayesian_Ttest/cyberTtest.R")
#read normalized GEO data (accession ID: GSE57084)
handel.normalized.matrix<-read.csv("../Data/Differential_expression_analysis/GEO_Handel2014/Handel_normalized_GEO_data.csv",header=T,row.names = 1)
#read map between microarray probe IDs and loci
probes.to.loci.map<-read.csv("../Data/Differential_expression_analysis/GEO_Handel2014/probes_loci_array_map.csv",header = T,row.names=1)
probes.to.loci.map<-as.matrix(probes.to.loci.map)
#replace probe names in expression matrix with locus tags
rownames(handel.normalized.matrix)<-probes.to.loci.map[rownames(handel.normalized.matrix),"ORF"]
#function to count the number of TFs, efflux pump genes and metabolic genes among significantly up- and down-regulated genes
classify.degs<-function(geneSet,expression.change) 
{
  output<-c()
  if(expression.change=="UP")
  {
    #count TF genes
    up.tfs<-length(intersect(geneSet,tf.names))
    #print names of up-regulated TFs
    if(up.tfs!=0)
    {
    convert.locus.to.gene.name(intersect(geneSet,tf.names))
    }
    #count efflux pump genes (eps)
    up.eps<-length(intersect(geneSet,effluxPump.genes))
    #print names of up-regulated eps
    if(up.eps!=0)
    {
    convert.locus.to.gene.name(intersect(geneSet,effluxPump.genes))
    }
    #count up-regulated metabolic genes
    up.metabolic<-length(intersect(geneSet,metabolic.genes))
    #count other up-regulated genes
    up.others<-length(geneSet)-(up.tfs+up.eps+up.metabolic)
    #compile values in a single vector
    output<-cbind(up.others,up.metabolic,up.tfs,up.eps)
  }
    if(expression.change=="DOWN")
    {
    #count TF genes
    down.tfs<- -1*length(intersect(geneSet,tf.names))
    #print names of down-regulated TFs
    if(down.tfs!=0)
    {
    convert.locus.to.gene.name(intersect(geneSet,tf.names))
    }
    #count efflux pump genes (eps)
    down.eps<- -1*length(intersect(geneSet,effluxPump.genes))
    #print names of down-regulated eps
    if(down.eps!=0)
    {
    convert.locus.to.gene.name(intersect(geneSet,effluxPump.genes))
    }
    #count down-regulated metabolic genes
    down.metabolic<- -1* length(intersect(geneSet,metabolic.genes))
    #count other down-regulated genes
    down.others<- -1*length(geneSet)-(down.tfs+down.eps+down.metabolic)
    #compile values in a single vector
    output<-cbind(down.others,down.metabolic,down.tfs,down.eps)
  }
  output
}
#run differential expression analyses 
#WT response to tetracycline: WT(+TET) vs WT(-TET) 
wt.response<-bayesT(handel.normalized.matrix[,1:6],numC = 3,numE = 3,conf = 7,doMulttest = T)
#define set of differentially expressed genes (DEGs)
wt.response.degs<-rownames(wt.response)[which(wt.response$BH < 0.05 & abs(wt.response$meanC - wt.response$meanE)>1)]
print(paste("WT differentially expressed",length(wt.response.degs),"genes in response to tetracycline",sep=" "))
[1] "WT differentially expressed 93 genes in response to tetracycline"
#create vector with fold-change for all genes
wt.response.fold.change<-wt.response$meanE - wt.response$meanC
names(wt.response.fold.change)<-rownames(wt.response)
#define sets of up- and down-regulated genes
wt.deg.up<-wt.response.degs[which(wt.response.fold.change[wt.response.degs]>0)]
wt.deg.down<-wt.response.degs[which(wt.response.fold.change[wt.response.degs]<0)]
#write CSV files with up- and down-regulated genes for downstream analysis on DAVID 
#write.csv(file="../Data/Differential_expression_analysis/DAVID_enrichment_analysis/Input/wt_response_up_080822.csv",wt.deg.up,row.names = F)
#write.csv(file="../Data/Differential_expression_analysis/DAVID_enrichment_analysis/Input/wt_response_down_080822.csv",wt.deg.down,row.names = F)
#count TFs, efflux pumps, metabolic genes and other genes in the up- and down-regulated genes
up.wt.vector<-classify.degs(wt.deg.up,"UP")
down.wt.vector<-classify.degs(wt.deg.down,"DOWN")
#differential expression analysis for TetR baseline change: TetR(-TET) vs WT(-TET)
tetR.basal<-bayesT(handel.normalized.matrix[,c(1:3,7:9)],numC = 3,numE = 3,conf = 7,doMulttest = T)
#define DEGs
tetR.basal.degs<-rownames(tetR.basal)[which(tetR.basal$BH < 0.05 & abs(tetR.basal$meanC - tetR.basal$meanE)>1)]
print(paste("TetR (-TET) differentially expressed",length(tetR.basal.degs),"genes with respect to WT(-TET)",sep=" "))
[1] "TetR (-TET) differentially expressed 197 genes with respect to WT(-TET)"
#save fold-change for all genes
tetR.basal.fold.change<-tetR.basal$meanE - tetR.basal$meanC
names(tetR.basal.fold.change)<-rownames(tetR.basal)
#define sets of up- and down-regulated genes
tetR.basal.degs.up<-tetR.basal.degs[which(tetR.basal.fold.change[tetR.basal.degs]>0)]
tetR.basal.degs.down<-tetR.basal.degs[which(tetR.basal.fold.change[tetR.basal.degs]<0)]
#write CSV files with up- and down-regulated genes for downstream analysis on DAVID 
#write.csv(file="../Data/Differential_expression_analysis/DAVID_enrichment_analysis/Input/tetR_basal_up_080822.csv",tetR.basal.degs.up,row.names = F)
#write.csv(file="../Data/Differential_expression_analysis/DAVID_enrichment_analysis/Input/tetR_basal_down_080822.csv",tetR.basal.degs.down,row.names = F)
#count TFs, efflux pumps, metabolic genes and other genes in the up- and down-regulated genes
up.tetR.basal.vector<-classify.degs(tetR.basal.degs.up,"UP")
down.tetR.basal.vector<-classify.degs(tetR.basal.degs.down,"DOWN")
#differential expression analysis for TetR response to tetracycline: TetR(+) vs TetR(-) 
tetR.response<-bayesT(handel.normalized.matrix[,7:12],numC = 3,numE = 3,conf = 7,doMulttest = T)
#define DEGs
tetR.response.degs<-rownames(tetR.response)[which(tetR.response$BH < 0.05 & abs(tetR.response$meanC - tetR.response$meanE)>1)]
print(paste("TetR differentially expressed",length(tetR.response.degs),"genes in response to tetracycline",sep=" "))
[1] "TetR differentially expressed 896 genes in response to tetracycline"
#save fold-change for all genes
tetR.response.fold.change<-tetR.response$meanE - tetR.response$meanC
names(tetR.response.fold.change)<-rownames(tetR.response)
#define sets of up- and down-regulated genes
tetR.response.degs.up<-tetR.response.degs[which(tetR.response.fold.change[tetR.response.degs]>0)]
tetR.response.degs.down<-tetR.response.degs[which(tetR.response.fold.change[tetR.response.degs]<0)]
#write CSV files with up- and down-regulated genes for downstream analysis on DAVID 
#write.csv(file="../Data/Differential_expression_analysis/DAVID_enrichment_analysis/Input/tetR_response_up_080822.csv",tetR.response.degs.up,row.names = F)
#write.csv(file="../Data/Differential_expression_analysis/DAVID_enrichment_analysis/Input/tetR_response_down_080822.csv",tetR.response.degs.down,row.names = F)
#count TFs, efflux pumps, metabolic genes and other genes in the up- and down-regulated genes
up.tetR.response.vector<-classify.degs(tetR.response.degs.up,"UP")
down.tetR.response.vector<-classify.degs(tetR.response.degs.down,"DOWN")
#differential expression analysis for TetR(+TET) vs WT(+TET)
tetR.wt.response.comparison<-bayesT(handel.normalized.matrix[,c(4:6,10:12)],numC = 3,numE = 3,conf = 7,doMulttest = T)
tetR.wt.response.comparison.degs<-rownames(tetR.wt.response.comparison)[which(tetR.wt.response.comparison$BH < 0.05 & abs(tetR.wt.response.comparison$meanC - tetR.wt.response.comparison$meanE)>1)]
print(paste("TetR (+TET) differentially expressed",length(tetR.wt.response.comparison.degs),"genes with respect to WT(+TET)",sep=" "))
[1] "TetR (+TET) differentially expressed 1005 genes with respect to WT(+TET)"
#save fold-change for all genes
tetR.wt.response.comparison.fold.change<-tetR.wt.response.comparison$meanE - tetR.wt.response.comparison$meanC
names(tetR.wt.response.comparison.fold.change)<-rownames(tetR.wt.response.comparison)
#define sets of up- and down-regulated genes
tetR.wt.response.comparison.degs.up<-tetR.wt.response.comparison.degs[which(tetR.wt.response.comparison.fold.change[tetR.wt.response.comparison.degs]>0)]
tetR.wt.response.comparison.degs.down<-tetR.wt.response.comparison.degs[which(tetR.wt.response.comparison.fold.change[tetR.wt.response.comparison.degs]<0)]
#count TFs, efflux pumps, metabolic genes and other genes in the up- and down-regulated genes
up.tetR.wt.response.comparison.vector<-classify.degs(tetR.wt.response.comparison.degs.up,"UP")
down.tetR.wt.response.comparison.vector<-classify.degs(tetR.wt.response.comparison.degs.down,"DOWN")
#create Figure 1A
#vector to generate blank space
zero.vector<-rep(0,4)
#selected colors for barplot
colors.barplot<-c("grey",rgb(253,174,97,maxColorValue = 255),rgb(166,217,106,maxColorValue = 255),rgb(215,25,28,maxColorValue = 255))
#generate barplot
#first, information regarding up-regulated genes
barplot(t(rbind(up.wt.vector,up.tetR.basal.vector,up.tetR.response.vector,up.tetR.wt.response.comparison.vector,zero.vector)),density=rep(15,4) 
        , angle=c(0,45,90,135) , col=colors.barplot,ylim=c(-500,500),ylab="Number of DEGs",main="Fig. 1A")
#then, add information regarding down-regulated genes is added
barplot(t(rbind(down.wt.vector,down.tetR.basal.vector,down.tetR.response.vector,down.tetR.wt.response.comparison.vector,zero.vector)),density=rep(15,4) , angle=c(0,45,90,135) ,col=colors.barplot,add=T)
abline(h=0,col="black",lwd=2)

1.3 Create Fig. S1

#Fig. S1 (fold-change of transcript level of fermentation-related genes)
#list of fermentation-related genes, compiled from EcoCyc database
fermentation.ecocyc<-read.csv("../Data/Input/fermentation_pathway_ecocyc.csv",header=F)
#function to translate gene name to locus tag
translate.gene.name.to.locus<-function(geneSet)
{
  output<-c()
  for(g in geneSet)
  {
  gene.pos<-grep(paste(g,"_",sep=""),rownames(transcriptional.network))
  if(length(gene.pos)==1)
  {
    output<-c(output,strsplit(rownames(transcriptional.network)[gene.pos],split="_")[[1]][2])
  }
  else
  {
    output<-c(output,g)
  }
  }
  output
}
#convert gene names to locus tags
fermentation.loci<-translate.gene.name.to.locus(fermentation.ecocyc[,1])
#add missing loci
fermentation.loci[15:16]<-c("b1675","b2929")
#create matrix with average expression value for WT and TetR strains in the presence/absence of tetracycline
handel.average.expression<-cbind(rowMeans(handel.normalized.matrix[,1:3]),rowMeans(handel.normalized.matrix[,4:6]),rowMeans(handel.normalized.matrix[,7:9]),rowMeans(handel.normalized.matrix[,10:12]))
#define matrix with average expression profile of fermentation genes
fermentation.pathway.average.expression.matrix<-handel.average.expression[as.vector(fermentation.loci),]
#add gene names information as rownames
rownames(fermentation.pathway.average.expression.matrix)<-as.vector(fermentation.ecocyc$V1)
#add column names
colnames(fermentation.pathway.average.expression.matrix)<-c("WT(-TET)","WT(+TET)", "TetR(-TET)", "TetR(+TET)")
#create heatmap displaying log2 fold-change with respect to untreated WT
#heatmap fold-change breaks
heatmap.breaks<-c(-3,-2,-1,-0.5,0,0.5,1,2)
#heatmap color palette
heatmap.colors<-colorRampPalette(rev(brewer.pal(7, "RdBu")) )(8)[8:1]
pheatmap(fermentation.pathway.average.expression.matrix[,2:4]-fermentation.pathway.average.expression.matrix[,1],scale="none",color =heatmap.colors[-5],cluster_rows=F,cluster_cols = F,fontsize = 8,angle_col = 90,
         breaks = heatmap.breaks,legend_breaks=heatmap.breaks,legend=T, main="Fig. S1")

#evaluate significance of fold-change using random permutation
#total permutations
N=10000
#average fold change of fermentation genes in the baseline change in TetR
true.average.fold.change.fermetation<-mean(fermentation.pathway.average.expression.matrix[,3]-fermentation.pathway.average.expression.matrix[,1])
random.average.fold.change<-c()
for(n in 1:N)
{
  random.selected.genes<-sample(1:nrow(handel.normalized.matrix),length(fermentation.loci))
  random.fold.change<-handel.average.expression[random.selected.genes,3]- handel.average.expression[random.selected.genes,1]
  random.average.fold.change<-c(random.average.fold.change,mean(random.fold.change))
}
#permutation p-value
permutation.pval.fermentation.genes<-length(which(abs(random.average.fold.change) >= true.average.fold.change.fermetation))/N
print(paste("Permutation p-value =",permutation.pval.fermentation.genes),
      sep="")
[1] "Permutation p-value = 0.0062"

1.4 Create Fig. S2 (acrA, acrB and acrZ expression and fitness profile in the presence of tetracycline)

#efflux pump genes of interest
acrA<-"b0463"
acrB<-"b0462"
acrZ<-"b0762"
#create Fig. S2A - expression profiles of selected genes
selected.genes.average.expression.matrix<-handel.average.expression[c(acrA,acrB,acrZ),2:4]-handel.average.expression[c(acrA,acrB,acrZ),1]
par(mfrow=c(1,1))
selected.genes.average.expression.matrix<-as.matrix(selected.genes.average.expression.matrix)
#add names of columns
colnames(selected.genes.average.expression.matrix)<-c("WT(+)","TetR(-)","TetR(+)")
#create barplot
barplot(selected.genes.average.expression.matrix,beside=T,col=c(rgb(141,160,203,maxColorValue = 255),rgb(252,141,98,maxColorValue = 255),rgb(102,194,165,maxColorValue = 255)),ylab="Log2 fold-change (vs. WT control)",ylim=c(-0.5,1.5),main="Fig. S2A")
 legend("topleft",fill=c(rgb(141,160,203,maxColorValue = 255),rgb(252,141,98,maxColorValue = 255),rgb(102,194,165,maxColorValue = 255)),legend = 
       c("AcrA","AcrB","AcrZ"))

#Fig. S2B
#load fitness data from Nichols et al. (Cell 2011)
fitness.scores<-read.xls("../Data/Miscellaneous_files/phenotipic landscape table s2.xls",header=T,fill=T)
#create boxplot for selected genes in tetracycline conditions
tetracycline.conditions<-grep("TETRACYCLINE",colnames(fitness.scores))
boxplot(ylim=c(-12,2),t(fitness.scores[c(3965,1278,2819),tetracycline.conditions]),
        col=c(rgb(141,160,203,maxColorValue = 255),rgb(252,141,98,maxColorValue = 255),rgb(102,194, 165,maxColorValue = 255)),outline=T,boxlty=1,whisklty = 1, staplelty = 1, names=c("acrA*","acrB*","acrZ"),frame=F,ylab="Deletion fitness score in tetracycline",cex.lab=1.1,main="Fig. S2B")
abline(h=0,lty=2)

1.5 Create Fig. 1B and accompanying Table S2

#perform differential expression analysis for TetR(+TET) vs WT(-TET)
tetR.plus.vs.WT.minus<-bayesT(handel.normalized.matrix[,c(1:3,10:12)],numC = 3,numE = 3,conf = 7,doMulttest = T)
#define DEGs
tetR.plus.vs.WT.minus.degs<-rownames(tetR.plus.vs.WT.minus)[which(tetR.plus.vs.WT.minus$BH < 0.05 & abs(tetR.plus.vs.WT.minus$meanC - tetR.plus.vs.WT.minus$meanE)>1)]
print(paste("TetR(+TET) differentially expressed",length(tetR.plus.vs.WT.minus.degs),"genes with respect to WT(-TET)",sep=" "))
[1] "TetR(+TET) differentially expressed 932 genes with respect to WT(-TET)"
#define fold-change vector
tetR.plus.vs.WT.minus.fold.change<-tetR.plus.vs.WT.minus$meanE - tetR.plus.vs.WT.minus$meanC
names(tetR.plus.vs.WT.minus.fold.change)<-rownames(tetR.plus.vs.WT.minus)
#define up- and down-regulated genes
tetR.plus.vs.WT.minus.degs.up<-tetR.plus.vs.WT.minus.degs[which(tetR.plus.vs.WT.minus.fold.change[tetR.plus.vs.WT.minus.degs]>0)]
tetR.plus.vs.WT.minus.degs.down<-tetR.plus.vs.WT.minus.degs[which(tetR.plus.vs.WT.minus.fold.change[tetR.plus.vs.WT.minus.degs]<0)]
#save CSV files with up- and down-regulated genes for downstream DAVID analysis
#write.csv(file="../Data/Differential_expression_analysis/DAVID_enrichment_analysis/Input/tetR+TET_WT-TET_upregulated_081522.csv",tetR.plus.vs.WT.minus.degs.up,row.names = F)
#write.csv(file="../Data/Differential_expression_analysis/DAVID_enrichment_analysis/Input/tetR+TET_WT-TET_downregulated_081522.csv",tetR.plus.vs.WT.minus.degs.down,row.names = F)
#Fig. 1B - Heatmap for selected functional terms
#read DAVID output files (i.e. functional enrichment) for WT response
#compile set of terms associated with WT response (down-regulated genes)
david.wt.response.down<-read.csv("../Data/Differential_expression_analysis/DAVID_enrichment_analysis/Output/Latest_output_2022/david_wt_response_down.csv",header=T)
significant.terms.wt.response.down<-as.character(david.wt.response.down$Term[which(david.wt.response.down$Benjamini < 0.05)])
#start vector with all enriched terms
all.enriched.terms<-significant.terms.wt.response.down
#compile set of terms associated with up-regulated genes as part of the WT response
david.wt.response.up<-read.csv("../Data/Differential_expression_analysis/DAVID_enrichment_analysis/Output/Latest_output_2022/david_wt_response_up.csv",header=T)
significant.terms.wt.response.up<-as.character(david.wt.response.up$Term[which(david.wt.response.up$Benjamini < 0.05)])
#add enriched terms to vector with all over-represented terms
all.enriched.terms<-union(all.enriched.terms,significant.terms.wt.response.up)
#read DAVID output (i.e. functional enrichment) for TetR basaline changes
#define set of terms associated with TetR basal response (down-regulated genes) 
david.tetR.basal.down<-read.csv("../Data/Differential_expression_analysis/DAVID_enrichment_analysis/Output/Latest_output_2022/david_tetR_basal_down.csv",header=T)
significant.terms.tetR.basal.down<-as.character(david.tetR.basal.down$Term[which(david.tetR.basal.down$Benjamini < 0.05)])
#add enriched terms to vector with all over-represented terms
all.enriched.terms<-union(all.enriched.terms,significant.terms.tetR.basal.down)
#define set of terms associated with up-regulated genes as part of the TetR basal response
david.tetR.basal.up<-read.csv("../Data/Differential_expression_analysis/DAVID_enrichment_analysis/Output/Latest_output_2022/david_tetR_basal_up.csv",header=T)
significant.terms.tetR.basal.up<-as.character(david.tetR.basal.up$Term[which(david.tetR.basal.up$Benjamini < 0.05)])
#add enriched terms to vector with all over-represented terms
all.enriched.terms<-union(all.enriched.terms,significant.terms.tetR.basal.up)
#read DAVID output (i.e. functional enrichment) for TetR(+TET) vs WT(-TET) 
#define set of terms associated with down-regulated genes
david.tetR.response.down<-read.csv("../Data/Differential_expression_analysis/DAVID_enrichment_analysis/Output/Latest_output_2022/david_tetR_plus_vs_wt_minus_down.csv",header=T)
significant.terms.tetR.response.down<-as.character(david.tetR.response.down$Term[which(david.tetR.response.down$Benjamini < 0.05)])
#add enriched terms to vector with all over-represented terms
all.enriched.terms<-union(all.enriched.terms,significant.terms.tetR.response.down)
#define set of terms associated with up-regulated genes
david.tetR.response.up<-read.csv("../Data/Differential_expression_analysis/DAVID_enrichment_analysis/Output/Latest_output_2022/david_tetR_plus_vs_wt_minus_up.csv",header=T)
significant.terms.tetR.response.up<-as.character(david.tetR.response.up$Term[which(david.tetR.response.up$Benjamini < 0.05)])
#add enriched terms to vector with all over-represented terms
all.enriched.terms<-union(all.enriched.terms,significant.terms.tetR.response.up)
#create matrix with information for all three comparisons with respect to the untreated WT strain
functional.enrichment.matrix<-matrix(ncol=3,nrow=length(all.enriched.terms),dimnames = list(all.enriched.terms,c("WT(+)","TetR(-)","TetR(+)")),0)
#fill out the  enrichment matrix 
#up- and down-regulated genes are indicated as 1s and -1s, respectively
#fill first column: WT(+) vs WT(-)
functional.enrichment.matrix[significant.terms.wt.response.down,"WT(+)"]<- -1
functional.enrichment.matrix[significant.terms.wt.response.up,"WT(+)"]<- 1
#fill second column: TetR(-) vs WT(-) 
functional.enrichment.matrix[significant.terms.tetR.basal.down,"TetR(-)"]<- -1
functional.enrichment.matrix[significant.terms.tetR.basal.up,"TetR(-)"]<- 1
#fill third column: TetR(+) vs WT(-)
functional.enrichment.matrix[significant.terms.tetR.response.down,"TetR(+)"]<- -1
functional.enrichment.matrix[significant.terms.tetR.response.up,"TetR(+)"]<- 1
#create sub-matrix with selected functional terms (for Fig. 1B)
#functional terms were manually selected
matrix.selected.terms<-functional.enrichment.matrix[c(1,15,19,26,31,23,25,28,17,39,38,71,81,51,41,48,75,77,74,49,50,61,52,58,73,82,80,84,87:89),]
#Fig. 1B
pheatmap(t(matrix.selected.terms),color =bluered(3)[3:1],scale = "none",cluster_rows=F,cluster_cols = F,
         fontsize = 8,angle_col = 90,main="Fig. 1B")

#create table S2
#initialize matrix
tableS2.matrix<-matrix(ncol=5,nrow=length(all.enriched.terms),
                         dimnames = list(all.enriched.terms,c("WT(+)","TetR(-)","TetR(+)","Total number of genes associated with term","P-value")),0)
#fill relevant information for over-represented terms in WT response  
#down-regulated terms 
for(t in significant.terms.wt.response.down)
 {
   term.position<-which(david.wt.response.down$Term == t)
   #fill row information
   tableS2.matrix[t,c(1,4)]<- as.matrix(david.wt.response.down[term.position,c("Count","Pop.Hits")])
   #add p-value information
   term.pval<-david.wt.response.down[term.position,"Benjamini"]
   if(tableS2.matrix[t,5]==0)
   {
     tableS2.matrix[t,5]<-term.pval
   }
   else
   {
     tableS2.matrix[t,5]<-paste(tableS2.matrix[t,5],term.pval,sep=";")
    }
}
#same process for up-regulated terms
for(t in significant.terms.wt.response.up)
 {
   term.position<-which(david.wt.response.up$Term == t)
   #fill row information
   tableS2.matrix[t,c(1,4)]<- as.matrix(david.wt.response.up[term.position,c("Count","Pop.Hits")])
   #add p-value information
   term.pval<-david.wt.response.up[term.position,"Benjamini"]
   if(tableS2.matrix[t,5]==0)
   {
     tableS2.matrix[t,5]<-term.pval
   }
   else
   {
     tableS2.matrix[t,5]<-paste(tableS2.matrix[t,5],term.pval,sep=";")
    }
}
 #fill information for TetR basal response column 
 #down-regulated terms  
  for(t in significant.terms.tetR.basal.down)
 {
   term.position<-which(david.tetR.basal.down$Term == t)
   tableS2.matrix[t,c(2,4)]<- as.matrix(david.tetR.basal.down[term.position,c("Count","Pop.Hits")])
   #add p-value information
   term.pval<-david.tetR.basal.down[term.position,"Benjamini"]
   if(tableS2.matrix[t,5]==0)
   {
     tableS2.matrix[t,5]<-term.pval
   }
   else
   {
     tableS2.matrix[t,5]<-paste(tableS2.matrix[t,5],term.pval,sep=";")
   }
  }
 #for up-regulated terms
 for(t in significant.terms.tetR.basal.up)
 {
   term.position<-which(david.tetR.basal.up$Term == t)
   tableS2.matrix[t,c(2,4)]<- as.matrix(david.tetR.basal.up[term.position,c("Count","Pop.Hits")])
   #add p-value information
   term.pval<-david.tetR.basal.up[term.position,"Benjamini"]
   if(tableS2.matrix[t,5]==0)
   {
     tableS2.matrix[t,5]<-term.pval
   }
   else
   {
     tableS2.matrix[t,5]<-paste(tableS2.matrix[t,5],term.pval,sep=";")
   }
 }
 #fill relevant information for TetR(+TET) vs WT(-TET) 
 #down-regulated terms  
 for(t in significant.terms.tetR.response.down)
 {
   term.position<-which(david.tetR.response.down$Term == t)
   tableS2.matrix[t,c(3,4)]<- as.matrix(david.tetR.response.down[term.position,c("Count","Pop.Hits")])
   #add p-value information
   term.pval<-david.tetR.response.down[term.position,"Benjamini"]
   if(tableS2.matrix[t,5]==0)
   {
     tableS2.matrix[t,5]<-term.pval
   }
   else
   {
     tableS2.matrix[t,5]<-paste(tableS2.matrix[t,5],term.pval,sep=";")
   }
 }
 #for up-regulated terms  
 for(t in significant.terms.tetR.response.up)
 {
   term.position<-which(david.tetR.response.up$Term == t)
   tableS2.matrix[t,c(3,4)]<- as.matrix(david.tetR.response.up[term.position,c("Count","Pop.Hits")])
   #add p-value information
   term.pval<-david.tetR.response.up[term.position,"Benjamini"]
   if(tableS2.matrix[t,5]==0)
   {
    tableS2.matrix[t,5]<-term.pval
   }
   else
   {
     tableS2.matrix[t,5]<-paste(tableS2.matrix[t,5],term.pval,sep=";")
   }
 }
print(tableS2.matrix)
                                                                                                WT(+) TetR(-) TetR(+)
GO:0015803~branched-chain amino acid transport                                                  "5"   "0"     "0"    
GO:0006865~amino acid transport                                                                 "8"   "0"     "0"    
GO:0098713~leucine import across plasma membrane                                                "4"   "0"     "0"    
KW-0029~Amino-acid transport                                                                    "8"   "0"     "0"    
GO:0015658~branched-chain amino acid transmembrane transporter activity                         "4"   "0"     "0"    
GO:0005304~L-valine transmembrane transporter activity                                          "4"   "0"     "0"    
GO:0015188~L-isoleucine transmembrane transporter activity                                      "4"   "0"     "0"    
GO:1903714~isoleucine transmembrane transport                                                   "4"   "0"     "0"    
eco02024:Quorum sensing                                                                         "7"   "0"     "0"    
GO:0015190~L-leucine transmembrane transporter activity                                         "4"   "0"     "0"    
GO:0015823~phenylalanine transport                                                              "4"   "0"     "0"    
GO:1903785~L-valine transmembrane transport                                                     "4"   "0"     "0"    
GO:0055052~ATP-binding cassette (ABC) transporter complex, substrate-binding subunit-containing "5"   "0"     "0"    
GO:0015192~L-phenylalanine transmembrane transporter activity                                   "3"   "0"     "0"    
eco02010:ABC transporters                                                                       "7"   "0"     "0"    
KW-0813~Transport                                                                               "13"  "0"     "0"    
KW-0346~Stress response                                                                         "7"   "19"    "38"   
KW-0805~Transcription regulation                                                                "9"   "0"     "53"   
KW-0804~Transcription                                                                           "9"   "0"     "53"   
KW-0732~Signal                                                                                  "15"  "0"     "0"    
KW-0658~Purine biosynthesis                                                                     "0"   "6"     "8"    
GO:0006164~purine nucleotide biosynthetic process                                               "0"   "6"     "0"    
GO:0006189~'de novo' IMP biosynthetic process                                                   "0"   "5"     "0"    
eco01110:Biosynthesis of secondary metabolites                                                  "0"   "20"    "130"  
GO:0044205~'de novo' UMP biosynthetic process                                                   "0"   "4"     "0"    
eco00230:Purine metabolism                                                                      "0"   "9"     "0"    
GO:0006207~'de novo' pyrimidine nucleobase biosynthetic process                                 "0"   "4"     "0"    
KW-0210~Decarboxylase                                                                           "0"   "5"     "0"    
GO:0006221~pyrimidine nucleotide biosynthetic process                                           "0"   "4"     "0"    
KW-0665~Pyrimidine biosynthesis                                                                 "0"   "4"     "7"    
eco00240:Pyrimidine metabolism                                                                  "0"   "7"     "0"    
KW-1134~Transmembrane beta strand                                                               "0"   "6"     "0"    
eco01230:Biosynthesis of amino acids                                                            "0"   "0"     "67"   
KW-0028~Amino-acid biosynthesis                                                                 "0"   "0"     "52"   
GO:0008652~cellular amino acid biosynthetic process                                             "0"   "0"     "52"   
eco01100:Metabolic pathways                                                                     "0"   "0"     "235"  
GO:0003824~catalytic activity                                                                   "0"   "0"     "93"   
eco01200:Carbon metabolism                                                                      "0"   "0"     "48"   
eco00250:Alanine, aspartate and glutamate metabolism                                            "0"   "0"     "22"   
KW-0816~Tricarboxylic acid cycle                                                                "0"   "0"     "16"   
GO:0006099~tricarboxylic acid cycle                                                             "0"   "0"     "18"   
GO:0005829~cytosol                                                                              "0"   "0"     "194"  
KW-0007~Acetylation                                                                             "0"   "0"     "40"   
eco01120:Microbial metabolism in diverse environments                                           "0"   "0"     "82"   
KW-0055~Arginine biosynthesis                                                                   "0"   "0"     "11"   
GO:0006526~arginine biosynthetic process                                                        "0"   "0"     "11"   
GO:0042802~identical protein binding                                                            "0"   "0"     "97"   
eco00190:Oxidative phosphorylation                                                              "0"   "0"     "23"   
GO:0009060~aerobic respiration                                                                  "0"   "0"     "14"   
GO:0006096~glycolytic process                                                                   "0"   "0"     "12"   
eco01210:2-Oxocarboxylic acid metabolism                                                        "0"   "0"     "16"   
eco00220:Arginine biosynthesis                                                                  "0"   "0"     "13"   
BINDING:Substrate                                                                               "0"   "0"     "58"   
KW-0324~Glycolysis                                                                              "0"   "0"     "11"   
GO:0016491~oxidoreductase activity                                                              "0"   "0"     "74"   
GO:0006541~glutamine metabolic process                                                          "0"   "0"     "10"   
eco00650:Butanoate metabolism                                                                   "0"   "0"     "18"   
eco00340:Histidine metabolism                                                                   "0"   "0"     "8"    
KW-0368~Histidine biosynthesis                                                                  "0"   "0"     "8"    
GO:0000105~histidine biosynthetic process                                                       "0"   "0"     "8"    
eco00010:Glycolysis / Gluconeogenesis                                                           "0"   "0"     "21"   
ACT_SITE:Proton donor                                                                           "0"   "0"     "35"   
GO:0030170~pyridoxal phosphate binding                                                          "0"   "0"     "20"   
KW-0315~Glutamine amidotransferase                                                              "0"   "0"     "8"    
GO:0006974~cellular response to DNA damage stimulus                                             "0"   "0"     "54"   
eco00020:Citrate cycle (TCA cycle)                                                              "0"   "0"     "15"   
GO:0051287~NAD binding                                                                          "0"   "0"     "16"   
GO:0006094~gluconeogenesis                                                                      "0"   "0"     "9"    
GO:0006520~cellular amino acid metabolic process                                                "0"   "0"     "12"   
GO:0006807~nitrogen compound metabolic process                                                  "0"   "0"     "10"   
eco00620:Pyruvate metabolism                                                                    "0"   "0"     "22"   
eco00680:Methane metabolism                                                                     "0"   "0"     "15"   
KW-0100~Branched-chain amino acid biosynthesis                                                  "0"   "0"     "9"    
KW-0830~Ubiquinone                                                                              "0"   "0"     "9"    
GO:0030964~NADH dehydrogenase complex                                                           "0"   "0"     "8"    
KW-0298~Galactitol metabolism                                                                   "0"   "0"     "5"    
KW-0874~Quinone                                                                                 "0"   "0"     "9"    
KW-0663~Pyridoxal phosphate                                                                     "0"   "0"     "20"   
eco00500:Starch and sucrose metabolism                                                          "0"   "0"     "15"   
eco00260:Glycine, serine and threonine metabolism                                               "0"   "0"     "15"   
eco00030:Pentose phosphate pathway                                                              "0"   "0"     "13"   
eco00400:Phenylalanine, tyrosine and tryptophan biosynthesis                                    "0"   "0"     "10"   
eco00310:Lysine degradation                                                                     "0"   "0"     "9"    
KW-1277~Toxin-antitoxin system                                                                  "0"   "0"     "22"   
KW-0238~DNA-binding                                                                             "0"   "0"     "65"   
GO:0003677~DNA binding                                                                          "0"   "0"     "73"   
eco00540:Lipopolysaccharide biosynthesis                                                        "0"   "0"     "11"   
KW-0281~Fimbrium                                                                                "0"   "0"     "10"   
KW-0229~DNA integration                                                                         "0"   "0"     "7"    
KW-0255~Endonuclease                                                                            "0"   "0"     "12"   
KW-0678~Repressor                                                                               "0"   "0"     "25"   
KW-0448~Lipopolysaccharide biosynthesis                                                         "0"   "0"     "14"   
KW-0540~Nuclease                                                                                "0"   "0"     "14"   
                                                                                                Total number of genes associated with term
GO:0015803~branched-chain amino acid transport                                                  "7"                                       
GO:0006865~amino acid transport                                                                 "87"                                      
GO:0098713~leucine import across plasma membrane                                                "4"                                       
KW-0029~Amino-acid transport                                                                    "79"                                      
GO:0015658~branched-chain amino acid transmembrane transporter activity                         "5"                                       
GO:0005304~L-valine transmembrane transporter activity                                          "5"                                       
GO:0015188~L-isoleucine transmembrane transporter activity                                      "5"                                       
GO:1903714~isoleucine transmembrane transport                                                   "5"                                       
eco02024:Quorum sensing                                                                         "64"                                      
GO:0015190~L-leucine transmembrane transporter activity                                         "6"                                       
GO:0015823~phenylalanine transport                                                              "6"                                       
GO:1903785~L-valine transmembrane transport                                                     "8"                                       
GO:0055052~ATP-binding cassette (ABC) transporter complex, substrate-binding subunit-containing "34"                                      
GO:0015192~L-phenylalanine transmembrane transporter activity                                   "4"                                       
eco02010:ABC transporters                                                                       "179"                                     
KW-0813~Transport                                                                               "732"                                     
KW-0346~Stress response                                                                         "150"                                     
KW-0805~Transcription regulation                                                                "337"                                     
KW-0804~Transcription                                                                           "343"                                     
KW-0732~Signal                                                                                  "479"                                     
KW-0658~Purine biosynthesis                                                                     "17"                                      
GO:0006164~purine nucleotide biosynthetic process                                               "18"                                      
GO:0006189~'de novo' IMP biosynthetic process                                                   "12"                                      
eco01110:Biosynthesis of secondary metabolites                                                  "339"                                     
GO:0044205~'de novo' UMP biosynthetic process                                                   "7"                                       
eco00230:Purine metabolism                                                                      "78"                                      
GO:0006207~'de novo' pyrimidine nucleobase biosynthetic process                                 "9"                                       
KW-0210~Decarboxylase                                                                           "21"                                      
GO:0006221~pyrimidine nucleotide biosynthetic process                                           "11"                                      
KW-0665~Pyrimidine biosynthesis                                                                 "11"                                      
eco00240:Pyrimidine metabolism                                                                  "57"                                      
KW-1134~Transmembrane beta strand                                                               "45"                                      
eco01230:Biosynthesis of amino acids                                                            "117"                                     
KW-0028~Amino-acid biosynthesis                                                                 "104"                                     
GO:0008652~cellular amino acid biosynthetic process                                             "103"                                     
eco01100:Metabolic pathways                                                                     "917"                                     
GO:0003824~catalytic activity                                                                   "375"                                     
eco01200:Carbon metabolism                                                                      "110"                                     
eco00250:Alanine, aspartate and glutamate metabolism                                            "33"                                      
KW-0816~Tricarboxylic acid cycle                                                                "23"                                      
GO:0006099~tricarboxylic acid cycle                                                             "29"                                      
GO:0005829~cytosol                                                                              "1051"                                    
KW-0007~Acetylation                                                                             "100"                                     
eco01120:Microbial metabolism in diverse environments                                           "268"                                     
KW-0055~Arginine biosynthesis                                                                   "12"                                      
GO:0006526~arginine biosynthetic process                                                        "12"                                      
GO:0042802~identical protein binding                                                            "456"                                     
eco00190:Oxidative phosphorylation                                                              "43"                                      
GO:0009060~aerobic respiration                                                                  "25"                                      
GO:0006096~glycolytic process                                                                   "19"                                      
eco01210:2-Oxocarboxylic acid metabolism                                                        "26"                                      
eco00220:Arginine biosynthesis                                                                  "18"                                      
BINDING:Substrate                                                                               "259"                                     
KW-0324~Glycolysis                                                                              "18"                                      
GO:0016491~oxidoreductase activity                                                              "356"                                     
GO:0006541~glutamine metabolic process                                                          "15"                                      
eco00650:Butanoate metabolism                                                                   "35"                                      
eco00340:Histidine metabolism                                                                   "8"                                       
KW-0368~Histidine biosynthesis                                                                  "10"                                      
GO:0000105~histidine biosynthetic process                                                       "10"                                      
eco00010:Glycolysis / Gluconeogenesis                                                           "47"                                      
ACT_SITE:Proton donor                                                                           "135"                                     
GO:0030170~pyridoxal phosphate binding                                                          "58"                                      
KW-0315~Glutamine amidotransferase                                                              "12"                                      
GO:0006974~cellular response to DNA damage stimulus                                             "250"                                     
eco00020:Citrate cycle (TCA cycle)                                                              "29"                                      
GO:0051287~NAD binding                                                                          "43"                                      
GO:0006094~gluconeogenesis                                                                      "15"                                      
GO:0006520~cellular amino acid metabolic process                                                "28"                                      
GO:0006807~nitrogen compound metabolic process                                                  "21"                                      
eco00620:Pyruvate metabolism                                                                    "59"                                      
eco00680:Methane metabolism                                                                     "33"                                      
KW-0100~Branched-chain amino acid biosynthesis                                                  "18"                                      
KW-0830~Ubiquinone                                                                              "15"                                      
GO:0030964~NADH dehydrogenase complex                                                           "14"                                      
KW-0298~Galactitol metabolism                                                                   "5"                                       
KW-0874~Quinone                                                                                 "14"                                      
KW-0663~Pyridoxal phosphate                                                                     "59"                                      
eco00500:Starch and sucrose metabolism                                                          "36"                                      
eco00260:Glycine, serine and threonine metabolism                                               "38"                                      
eco00030:Pentose phosphate pathway                                                              "32"                                      
eco00400:Phenylalanine, tyrosine and tryptophan biosynthesis                                    "21"                                      
eco00310:Lysine degradation                                                                     "18"                                      
KW-1277~Toxin-antitoxin system                                                                  "52"                                      
KW-0238~DNA-binding                                                                             "439"                                     
GO:0003677~DNA binding                                                                          "499"                                     
eco00540:Lipopolysaccharide biosynthesis                                                        "38"                                      
KW-0281~Fimbrium                                                                                "28"                                      
KW-0229~DNA integration                                                                         "14"                                      
KW-0255~Endonuclease                                                                            "45"                                      
KW-0678~Repressor                                                                               "150"                                     
KW-0448~Lipopolysaccharide biosynthesis                                                         "65"                                      
KW-0540~Nuclease                                                                                "70"                                      
                                                                                                P-value                        
GO:0015803~branched-chain amino acid transport                                                  "1.97e-06"                     
GO:0006865~amino acid transport                                                                 "1.09e-05"                     
GO:0098713~leucine import across plasma membrane                                                "1.52e-05"                     
KW-0029~Amino-acid transport                                                                    "2.35e-05"                     
GO:0015658~branched-chain amino acid transmembrane transporter activity                         "3.11e-05"                     
GO:0005304~L-valine transmembrane transporter activity                                          "3.11e-05"                     
GO:0015188~L-isoleucine transmembrane transporter activity                                      "3.11e-05"                     
GO:1903714~isoleucine transmembrane transport                                                   "2.83e-05"                     
eco02024:Quorum sensing                                                                         "6.71e-05"                     
GO:0015190~L-leucine transmembrane transporter activity                                         "4.65e-05"                     
GO:0015823~phenylalanine transport                                                              "4.52e-05"                     
GO:1903785~L-valine transmembrane transport                                                     "0.000105"                     
GO:0055052~ATP-binding cassette (ABC) transporter complex, substrate-binding subunit-containing "0.001528139"                  
GO:0015192~L-phenylalanine transmembrane transporter activity                                   "0.00217276"                   
eco02010:ABC transporters                                                                       "0.012294768"                  
KW-0813~Transport                                                                               "0.03394874"                   
KW-0346~Stress response                                                                         "0.015195191;3.54e-07;2.96e-08"
KW-0805~Transcription regulation                                                                "0.020194756;0.000159"         
KW-0804~Transcription                                                                           "0.020194756;0.000205"         
KW-0732~Signal                                                                                  "0.019683791"                  
KW-0658~Purine biosynthesis                                                                     "0.000683;0.042322923"         
GO:0006164~purine nucleotide biosynthetic process                                               "0.003311033"                  
GO:0006189~'de novo' IMP biosynthetic process                                                   "0.005360735"                  
eco01110:Biosynthesis of secondary metabolites                                                  "0.005379245;1.24e-21"         
GO:0044205~'de novo' UMP biosynthetic process                                                   "0.013707388"                  
eco00230:Purine metabolism                                                                      "0.00896889"                   
GO:0006207~'de novo' pyrimidine nucleobase biosynthetic process                                 "0.023952715"                  
KW-0210~Decarboxylase                                                                           "0.027863848"                  
GO:0006221~pyrimidine nucleotide biosynthetic process                                           "0.036542427"                  
KW-0665~Pyrimidine biosynthesis                                                                 "0.024787239;0.016901296"      
eco00240:Pyrimidine metabolism                                                                  "0.030058899"                  
KW-1134~Transmembrane beta strand                                                               "0.025790987"                  
eco01230:Biosynthesis of amino acids                                                            "9.12e-21"                     
KW-0028~Amino-acid biosynthesis                                                                 "3.82e-18"                     
GO:0008652~cellular amino acid biosynthetic process                                             "3.04e-17"                     
eco01100:Metabolic pathways                                                                     "1.7e-17"                      
GO:0003824~catalytic activity                                                                   "5.14e-08"                     
eco01200:Carbon metabolism                                                                      "8.82e-09"                     
eco00250:Alanine, aspartate and glutamate metabolism                                            "1.16e-07"                     
KW-0816~Tricarboxylic acid cycle                                                                "3.63e-07"                     
GO:0006099~tricarboxylic acid cycle                                                             "2.2e-06"                      
GO:0005829~cytosol                                                                              "2.54e-06"                     
KW-0007~Acetylation                                                                             "5.96e-07"                     
eco01120:Microbial metabolism in diverse environments                                           "1.05e-06"                     
KW-0055~Arginine biosynthesis                                                                   "2.22e-06"                     
GO:0006526~arginine biosynthetic process                                                        "1.28e-05"                     
GO:0042802~identical protein binding                                                            "5.87e-05"                     
eco00190:Oxidative phosphorylation                                                              "8.46e-06"                     
GO:0009060~aerobic respiration                                                                  "0.000443"                     
GO:0006096~glycolytic process                                                                   "0.000533"                     
eco01210:2-Oxocarboxylic acid metabolism                                                        "7.35e-05"                     
eco00220:Arginine biosynthesis                                                                  "7.35e-05"                     
BINDING:Substrate                                                                               "0.022461343"                  
KW-0324~Glycolysis                                                                              "0.000533"                     
GO:0016491~oxidoreductase activity                                                              "0.004362816"                  
GO:0006541~glutamine metabolic process                                                          "0.002348499"                  
eco00650:Butanoate metabolism                                                                   "0.000299"                     
eco00340:Histidine metabolism                                                                   "0.000374"                     
KW-0368~Histidine biosynthesis                                                                  "0.001063802"                  
GO:0000105~histidine biosynthetic process                                                       "0.00429118"                   
eco00010:Glycolysis / Gluconeogenesis                                                           "0.000546"                     
ACT_SITE:Proton donor                                                                           "0.039747134"                  
GO:0030170~pyridoxal phosphate binding                                                          "0.012233674"                  
KW-0315~Glutamine amidotransferase                                                              "0.001082243"                  
GO:0006974~cellular response to DNA damage stimulus                                             "0.008391287"                  
eco00020:Citrate cycle (TCA cycle)                                                              "0.00131638"                   
GO:0051287~NAD binding                                                                          "0.025496601"                  
GO:0006094~gluconeogenesis                                                                      "0.014112325"                  
GO:0006520~cellular amino acid metabolic process                                                "0.025133349"                  
GO:0006807~nitrogen compound metabolic process                                                  "0.036499498"                  
eco00620:Pyruvate metabolism                                                                    "0.005984965"                  
eco00680:Methane metabolism                                                                     "0.005984965"                  
KW-0100~Branched-chain amino acid biosynthesis                                                  "0.016901296"                  
KW-0830~Ubiquinone                                                                              "0.036820658"                  
GO:0030964~NADH dehydrogenase complex                                                           "0.04653206"                   
KW-0298~Galactitol metabolism                                                                   "0.016901296"                  
KW-0874~Quinone                                                                                 "0.006740967"                  
KW-0663~Pyridoxal phosphate                                                                     "0.036820658"                  
eco00500:Starch and sucrose metabolism                                                          "0.015420703"                  
eco00260:Glycine, serine and threonine metabolism                                               "0.026108837"                  
eco00030:Pentose phosphate pathway                                                              "0.037861334"                  
eco00400:Phenylalanine, tyrosine and tryptophan biosynthesis                                    "0.037861334"                  
eco00310:Lysine degradation                                                                     "0.043542725"                  
KW-1277~Toxin-antitoxin system                                                                  "2.19e-08"                     
KW-0238~DNA-binding                                                                             "2.06e-05"                     
GO:0003677~DNA binding                                                                          "0.000316"                     
eco00540:Lipopolysaccharide biosynthesis                                                        "0.000497"                     
KW-0281~Fimbrium                                                                                "0.002440319"                  
KW-0229~DNA integration                                                                         "0.009033247"                  
KW-0255~Endonuclease                                                                            "0.012831782"                  
KW-0678~Repressor                                                                               "0.012831782"                  
KW-0448~Lipopolysaccharide biosynthesis                                                         "0.034625247"                  
KW-0540~Nuclease                                                                                "0.040811911"                  

1.5 Fig. 1C-Expression profile of aerobic respiration related genes

#read list of TCA, electron transport chain and ATP synthase genes
aerobic.respiration.table<-read.csv("../Data/Input/aerobic_respiration_genes.csv")
aerobic.respiration.loci<-aerobic.respiration.table$Locus
aerobic.respiration.average.expression<-handel.average.expression[as.vector(aerobic.respiration.loci),]
rownames(aerobic.respiration.average.expression)<-aerobic.respiration.table$Name
#define heatmap breaks
heatmap.breaks<-c(-4,-2,-1,0,0.5,1,1.5)
pheatmap(aerobic.respiration.average.expression[,2:4]-aerobic.respiration.average.expression[,1],scale="none",color =colorRampPalette(rev(brewer.pal(6, "RdBu")) )(6)[6:1],
         cluster_rows=F,cluster_cols = F,fontsize = 8,angle_col = 90,
         breaks = heatmap.breaks,legend_breaks=heatmap.breaks,legend=T, main="Fig. 1C")

2.1 Table 1

#function to generate input files for NetSurgeon algorithm (Brent et al. PNAS 2016)
create.netSurgeon.input<-function(input.network,bayesian.ttest.output,name.output.file)
{
#change gene names (for both rows and columns) to loci in the input network
rownames(input.network)<-sapply(1:nrow(input.network),function(x){strsplit(rownames(input.network)[x],split="_")[[1]][2]})
colnames(input.network)<-sapply(1:ncol(input.network),function(x){strsplit(colnames(input.network)[x],split="_")[[1]][2]})
#define genes present in both datasets (i.e., expression matrix and transcriptional network)
genes.present.in.both.datasets<-intersect(rownames(bayesian.ttest.output),rownames(input.network))
#filter the transcriptional network accordingly
input.network<-input.network[genes.present.in.both.datasets,]
#remove from the TRN those TFs with less than five targets 
input.network<-input.network[,-1*which(colSums(abs(input.network))<5)]
#create input network for NetSurgeon 
#the format of the input network is TFs x Genes
#save input file
write.table(t(input.network),col.names=F,row.names=F,quote=F,file=paste("../Data/Network_analysis/NetSurgeon/Input/",name.output.file,"_",Sys.Date(),".mtr",sep=""))
#extract q-values from Bayesian T-tests
q.values<-bayesian.ttest.output[rownames(input.network),"BH"]
#replace zeroes with minimum q-value among the non-zero values to avoid infinity during the log conversion
position.zero.q.values<-which(q.values ==0)
if(length(position.zero.q.values)>0)
{
  q.values[position.zero.q.values]<-min(q.values[-1* position.zero.q.values])
}
#convert q-values of not differentially expressed genes to 1
q.values[which(q.values > 0.05 | abs(bayesian.ttest.output[rownames(input.network),"meanC"]-bayesian.ttest.output[rownames(input.network),"meanE"])<1)]=1
#estimate the sign of fold-change for each gene
fold.change.sign<- sign(bayesian.ttest.output[rownames(input.network), "fold"])
#sign -log q-values based on fold change direction
DEvector<- fold.change.sign * -log2(q.values) 
#remove any NA
DEvector[which(is.na(DEvector))]<-0
#save input files
write.table(DEvector,sep=" ",col.names=F,row.names=F,quote=F,file=paste("../Data/Network_analysis/NetSurgeon/Input/",name.output.file,"_",Sys.Date(),".vect",sep=""))
regulators<-colnames(input.network)
write.table(regulators,sep=" ",col.names=F,row.names=F,quote=F,file=paste("../Data/Network_analysis/NetSurgeon/Input/",name.output.file,"_",Sys.Date(),".tfs",sep=""))
targets<-rownames(input.network)
write.table(targets,sep=" ",col.names=F,row.names=F,quote=F,file=paste("../Data/Network_analysis/NetSurgeon/Input/",name.output.file,"_",Sys.Date(),".orfs",sep=""))
}
#create files for WT response to tetracycline
create.netSurgeon.input(input.network = transcriptional.network,bayesian.ttest.output = wt.response,name.output.file = "WT_TET")
#create files for TetR at baseline
create.netSurgeon.input(input.network = transcriptional.network,bayesian.ttest.output = tetR.basal,name.output.file = "TetR_basal")
#create files for TetR response to tetracycline
create.netSurgeon.input(input.network = transcriptional.network,bayesian.ttest.output = tetR.response,name.output.file = "TetR_response")
#read compiled NetSurgeon output to create Table 1 (only top 15 TFs for each comparison were considered as differentially active)
netsurgeon.output<-read.csv("../Data/Network_analysis/NetSurgeon/Output/table1_raw_compiled_NetSurgeon_output.csv",header=T)
#initialize table 1-add information about regulon size
table1<-c()
transcriptional.network.loci.tags<-transcriptional.network
#change row- and column names
rownames(transcriptional.network.loci.tags)<-sapply(1:nrow(transcriptional.network.loci.tags),function(x){strsplit(rownames(transcriptional.network.loci.tags)[x],split="_")[[1]][2]})
colnames(transcriptional.network.loci.tags)<-sapply(1:ncol(transcriptional.network.loci.tags),function(x){strsplit(colnames(transcriptional.network.loci.tags)[x],split="_")[[1]][2]})
temporal.table<-c()
for(tf in netsurgeon.output$Locus.tag)
{
  #number of targets of current TF
  regulon.size<-length(intersect(names(which(transcriptional.network.loci.tags[,tf]!=0)),rownames(handel.normalized.matrix)))
  #differentially expressed targets that are part of the baseline change
  de.targets.tetR.basal<-length(intersect(names(which(transcriptional.network.loci.tags[,tf]!=0)),tetR.basal.degs))
  #differentially expressed targets that are part of TetR response to tetracycline
  de.targets.tetR.adaptive<-length(intersect(names(which(transcriptional.network.loci.tags[,tf]!=0)),tetR.response.degs))
  #add collected information to table
  temporal.table<-rbind(temporal.table,cbind(regulon.size                                         ,de.targets.tetR.basal,de.targets.tetR.adaptive))
}
#add column names
colnames(temporal.table)<-c("Regulon size","Targets-basal","Targets-adaptive")
#combine netsurgeon output with temporal table
table1<-cbind(netsurgeon.output[,-1*2:4],temporal.table)
#add loci information
table1<-cbind(convert.locus.to.gene.name(table1[,"Locus.tag"]),table1)
colnames(table1)[1]<-"Transcription factor"
#print Table # 1
print(table1[order(table1[,"Regulon size"],decreasing = T),])
   Transcription factor Locus.tag Differential.activity Response Regulon size Targets-basal Targets-adaptive
14                 rpoS     b2741             Decreased Adaptive          207            20               69
24                 arcA     b4401             Increased Adaptive          167             9               66
7                   hns     b1237             Decreased    Basal          146            18               33
1                  fruR     b0080             Increased Adaptive           76             2               43
4                   lrp     b0889             Increased     Both           64             9               32
6                  phoP     b1130             Decreased    Basal           49             9               15
18                 gadE     b3512             Decreased     Both           36             9               14
9                  marA     b1531             Increased    Basal           33            11               11
13                 rcsB     b2217             Decreased    Basal           33             7               10
21                 soxS     b4062             Increased    Basal           33             7               13
11                 purR     b1658             Increased    Basal           31            10               10
23                  rob     b4396             Increased    Basal           22             8                7
12                 fliZ     b1921             Increased    Basal           20             6                6
16                 ompR     b3405             Increased     Both           13             4                6
19                 cytR     b3934             Increased Adaptive           13             0                8
5                  torR     b0995             Decreased    Basal           12             3                4
10                 dgsA     b1594             Increased Adaptive           10             0                7
17                 malT     b3418             Decreased Adaptive           10             0                8
2                  nrdR     b0413             Decreased Adaptive            9             1                4
3                  ybjK     b0846             Increased Adaptive            8             1                5
22                 adiY     b4116             Decreased     Both            8             3                5
8                  pspF     b1303             Increased     Both            7             4                5
15                 glcC     b2980             Increased    Basal            6             3                3
25                 gatR     b4498             Increased Adaptive            6             0                6
20                 birA     b3973             Decreased Adaptive            5             0                5
#evaluate how many DEGs are controlled by the 25 TFs
#all genes differentially expressed in the TetR strain background (baseline combined with adaptive response)
tetR.DEGs<-union(tetR.basal.degs,tetR.response.degs)
#compile genes that are differentially expressed by TetR and are regulated by the 25 TFs in NetSurgeon output
genes.affected.by.tetR.phenotype<-c()
for(tf in table1[,"Locus.tag"])
{
  #define members of current TF regulon that are differentially expressed in basal or adaptive response
  de.targets.tetR<-intersect(names(which(transcriptional.network.loci.tags[,tf]!=0)),tetR.DEGs)
  #add genes into compilation set
  genes.affected.by.tetR.phenotype<-union(genes.affected.by.tetR.phenotype,de.targets.tetR)
}
print(length(genes.affected.by.tetR.phenotype))
[1] 279
#similar analysis but counting DEGs controlled by the 15 TFs associated with TetR response to tetracycline (i.e., adaptive TFs)
#define adaptive TFs
adaptive.tfs<-table1[-1*(which(table1[,"Response"]=="Basal")),"Locus.tag"]
#vector with members of adaptive TFs that were differentially expressed by TetR in response to tetracycline
target.genes.tetR.response<-c()
#vector with all members of adaptive TF regulons
adaptive.tfs.total.targets<-c()
for(tf in adaptive.tfs)
{
  #define current TF regulon
  current.tf.regulon<-names(which(transcriptional.network.loci.tags[,tf]!=0))
  #define members of current TF regulon that were differentially expressed as part TetR adaptive response
  de.targets.adaptive<-intersect(current.tf.regulon,tetR.response.degs)
  #add genes into corresponding sets
  target.genes.tetR.response<-union(target.genes.tetR.response,de.targets.adaptive)
  adaptive.tfs.total.targets<-union(adaptive.tfs.total.targets,intersect(current.tf.regulon,rownames(handel.normalized.matrix)))
}
print(length(target.genes.tetR.response))
[1] 209
#compute hyper-geometric test p-value
phyper(length(target.genes.tetR.response)-1,length(adaptive.tfs.total.targets),nrow(handel.normalized.matrix)-length(adaptive.tfs.total.targets),length(tetR.response.degs),lower.tail = F)
[1] 2.091052e-27

2.2 Fig 2A: interactions among differentially active TFs

#initialize TF-TF network
tf.tf.network<-c()
#add TF-TF interactions that involve TFs included in Table 1
for(tf in 1:nrow(table1))
{
  #current TF
  tf.locus<-as.character(table1[tf,"Locus.tag"])
  tf.name<-as.character(table1[tf,"Transcription factor"])
  #TF regulon 
  tf.regulon<-names(which(transcriptional.network.loci.tags[,tf.locus]!=0))
  #target TFs - excluding autoregulation
  target.tfs<-setdiff(intersect(tf.regulon,as.character(table1[,"Locus.tag"])),tf.locus)
  #add relevant interactions
  if(length(target.tfs) > 0)
  {
    #sign (activation or repression) of TF-TF interactions
    interaction.signs<-sign(transcriptional.network.loci.tags[as.character(target.tfs),tf.locus])
    #expand the TF-TF network
    tf.tf.network<-rbind(tf.tf.network,cbind(rep(tf.name,length(target.tfs)),convert.locus.to.gene.name(target.tfs),interaction.signs))
  }
}
#add column names
colnames(tf.tf.network)<-c("Regulator","Target","Sign")
#extend the TF-TF network to take into account subset of target genes that were differentially expressed (DE) in TetR response
#focused on the 15 TFs associated with TetR adaptive response and their DE targets
temporal.subnetwork.matrix<-transcriptional.network.loci.tags[as.character(target.genes.tetR.response),adaptive.tfs]
#define unique profiles in transcriptional subnetwork (i.e., keeping a single row to represent all genes with the same regulators in the temporal.subnetwork.matrix)
unique.gene.profiles<-unique.matrix(temporal.subnetwork.matrix)
#groups of genes with same regulators
gene.groups<-list()
#regulators of each gene group
tf.groups<-c()
for (r in 1:nrow(unique.gene.profiles))
{
  temporal.gene.group<-c()
  current.profile<-unique.gene.profiles[r,]
  #define which genes in the temporal.subnetwork.matrix have the same profile (i.e., same regulators)
  for(g in target.genes.tetR.response)
  {
    if(apply(temporal.subnetwork.matrix[g,]==t(current.profile),1,all))
    {
      temporal.gene.group<-c(temporal.gene.group,g)
    }
  }
  #only save groups with more than five genes
  if(length(temporal.gene.group)>5)
  {
    gene.groups[[length(gene.groups)+1]]<-temporal.gene.group
    group.regulators<-convert.locus.to.gene.name(names(which(current.profile!=0)))
    tf.groups<-rbind(tf.groups,cbind(group.regulators,                              rep(paste("Group",length(gene.groups),sep=""),length(group.regulators)),length(temporal.gene.group)))
   write.csv(file=paste("../Data/Network_analysis/NetSurgeon/Output/temporal_coregulated_gene_groups_adaptive_response_g",length(gene.groups),"_",Sys.Date(),".csv",sep=""),gene.groups[[length(gene.groups)]])
    }
}
#add column names
colnames(tf.groups)<-c("Regulator","Target","#number of genes")
#merge the gene clusters with the TF-TF network
tf.tf.network.unsigned<-rbind(tf.tf.network[,1:2],tf.groups[,1:2])
#plot resulting gene network - Fig. 2A draft. 
#the TF-TF network in manuscript was visualized with Cytoscape
tf.tf.network.igraph.format<-graph_from_data_frame(tf.tf.network.unsigned                                              ,union(tf.tf.network.unsigned[,"Regulator"],tf.tf.network.unsigned[,"Target"]), directed = T)
selected.network.layout <- layout_nicely(tf.tf.network.igraph.format)
plot(tf.tf.network.igraph.format,layout = selected.network.layout, edge.arrow.size =0.2,vertex.label.cex=0.5,vertex.size=13,main="Fig. 2A (draft)")

#complement Netsurgeon results with analysis of E. coli EGRIN2 model (Brooks et al. 2014, MSB)
#read EGRIN2 corems (in simplified terms, a corem is a group of co-regulated genes)
ecoli.corems.table<-read.csv("../Data/Network_analysis/EGRIN_model/ecoli_egrin2_corems.csv")
#define E. coli corems
ecoli.corems<-list()
#save names of all genes included the E. coli EGRIN model
ecoli.egrin2.genes<-c()
#save number of genes in each corem
corems.size<-c()
for(s in 1:nrow(ecoli.corems.table))
{
  current.corem<-strsplit(as.character(ecoli.corems.table$Genes[s]),split=";",fixed = T)[[1]]
  ecoli.corems[[length(ecoli.corems)+1]]<-current.corem
  corems.size<-c(corems.size,length(current.corem))
  ecoli.egrin2.genes<-union(ecoli.egrin2.genes,current.corem)
}
#name corems as c1, c2, etc.
names(ecoli.corems)<-paste("c",1:length(ecoli.corems),sep="")
#function to identify corems enriched with a particular (user-specified) set of genes
evaluate.corem.enrichment<-function(corem.set,gene.set)
{
  #matrix with p-values
  corem.enrichment = matrix(nrow=length(corem.set),ncol=5)
  colnames(corem.enrichment)<-c('q','m','n','k','p_value')
  rownames(corem.enrichment)<-names(corem.set)
  for(x in 1:length(corem.set)) {
    q = length(intersect(corem.set[[x]],gene.set))
    m = length(corem.set[[x]])
    k = length(intersect(gene.set,unique(ecoli.egrin2.genes)))
    n = length(ecoli.egrin2.genes)-m
    pval = NA
    #if the intersect is bigger than zero
    if(q > 0) {
      #compute hypergeometric test p-value
      pval = phyper(q,m,n,k,lower.tail=F)
    }
    #add values to matrix
    corem.enrichment[x,] = c(q,m,n,k,pval)
  }
  #perform multiple hypotheses testing correction
  corem.enrichment = cbind(corem.enrichment,p_value.BH=p.adjust(corem.enrichment[,'p_value'],method='BH',n=nrow(corem.enrichment)))
  #select enriched corems with ten or more members
  final.enriched.corems = rownames(corem.enrichment)[which(corem.enrichment[,'p_value.BH']<=0.05 & corem.enrichment[,'m']> 9)]
  output<-corem.enrichment[final.enriched.corems,]
  output
}
#evaluate enrichment of EGRIN corems (also known as modules) with DEGs of TetR baseline and adaptive responses
modules.enriched.with.tetR.baseline<-evaluate.corem.enrichment(ecoli.corems, tetR.basal.degs)
modules.enriched.with.tetR.adaptive<-evaluate.corem.enrichment(ecoli.corems, tetR.response.degs)
#save names of TF regulons over-represented in corems enriched with TetR basaline changes
corems.enriched.with.tetR.basal.TF.regulons<-c()
#save names of TF regulons over-represented in corems enriched with TetR adaptive response 
corems.enriched.with.tetR.adaptive.TF.regulons<-c()
#save genes in corems enriched with both TetR DEGs AND targets of NetSurgeon predicted TFs
corems.enriched.with.tf.regulons.and.degs<-c()
#save ID of corems enriched with both gene sets
significant.corems<-c()
#-1*c(2,3,5,8,11,16,19,20)
for(tf in table1[,"Locus.tag"])
{
  current.regulon<-names(which(transcriptional.network.loci.tags[,tf]!=0))
  #identify corems enriched with current TF regulon
  temporal.enrichment.information<-evaluate.corem.enrichment(ecoli.corems, current.regulon)
  #define corems enriched with current TF regulon and TetR basal response
  intersect.corems<-intersect(rownames(modules.enriched.with.tetR.baseline),rownames(temporal.enrichment.information))
  #if there is one or more corems enriched with both gene sets
  if(length(intersect.corems)>0)
  {
    corems.enriched.with.tetR.basal.TF.regulons<-c(corems.enriched.with.tetR.basal.TF.regulons,tf)
    #compile members of the corems enriched with both gene sets
    for(c in intersect.corems)
    {
      corems.enriched.with.tf.regulons.and.degs<-union(corems.enriched.with.tf.regulons.and.degs,ecoli.corems[[c]])
      significant.corems<-union(significant.corems,c)
    }
  }
  #repeat analysis for TetR adaptive response
  #define corems enriched with current TF regulon and TetR adaptive response
  intersect.corems<-intersect(rownames(modules.enriched.with.tetR.adaptive),rownames(temporal.enrichment.information))
  if(length(intersect.corems)>0)
  {
    corems.enriched.with.tetR.adaptive.TF.regulons<-c(corems.enriched.with.tetR.adaptive.TF.regulons,tf)
    for(c in intersect.corems)
    {
      corems.enriched.with.tf.regulons.and.degs<-union(corems.enriched.with.tf.regulons.and.degs,ecoli.corems[[c]])
      significant.corems<-union(significant.corems,c)
    }
  }
}
#define final set of TFs identified by both NetSurgeon and EGRIN-based analysis
tfs.detected.by.egrin.analysis<-union(corems.enriched.with.tetR.basal.TF.regulons,corems.enriched.with.tetR.adaptive.TF.regulons)
print(convert.locus.to.gene.name(tfs.detected.by.egrin.analysis))
 [1] "lrp"  "torR" "phoP" "hns"  "pspF" "marA" "purR" "fliZ" "rcsB" "rpoS" "ompR" "gadE" "fruR" "dgsA" "malT" "cytR" "birA" "soxS" "rob"  "arcA" "gatR"
#identify TFs with differential regulatory activity (alternative approach)
#we first estimate TF activity
genes.present.in.transcriptional.network.and.expression.matrix<-intersect(rownames(transcriptional.network.loci.tags),rownames(handel.normalized.matrix))
final.trn.network<-transcriptional.network.loci.tags[genes.present.in.transcriptional.network.and.expression.matrix,]
#remove TFs with less than five target genes
final.trn.network<-final.trn.network[,-1 * which(colSums(abs(final.trn.network))<5)]
#keep only shared genes in the expression matrix
tetracycline.expression.matrix<-as.matrix(handel.normalized.matrix[genes.present.in.transcriptional.network.and.expression.matrix,])
#compute pseudoinverse of the transcriptional network
pseudoinverse.matrix <- pseudoinverse(final.trn.network)
#compute TF activities
estimated.tf.activities <- pseudoinverse.matrix %*% tetracycline.expression.matrix
rownames(estimated.tf.activities)<- colnames(final.trn.network)
#perform t-test to compare estimated TFAs across strains/conditions
#vector with p-values
tfa.pvals<-c()
#vector with regulon size
regulon.size<-c()
#vector with p-values for TetR basal response: TetR(-TET) vs WT(-TET)
pvalues.activity.tetR.basaline<-c()
#vector with p-values for TetR adaptive response: TetR(+TET) vs TetR(-TET)
pvalues.activity.tetR.adaptive<-c()
for(r in 1:nrow(estimated.tf.activities))
{
  #perform t-tests
  temporal.pvalue<-t.test(estimated.tf.activities[r,7:9],estimated.tf.activities[r,1:3])$p.value
  pvalues.activity.tetR.basaline<-c(pvalues.activity.tetR.basaline,temporal.pvalue)
  temporal.pvalue2<-t.test(estimated.tf.activities[r,7:9],estimated.tf.activities[r,10:12])$p.value
  pvalues.activity.tetR.adaptive<-c(pvalues.activity.tetR.adaptive,temporal.pvalue2)
}
#perform multiple hypothesis correction
ttest.activities.matrix<-cbind(estimated.tf.activities,pvalues.activity.tetR.basaline,p.adjust(pvalues.activity.tetR.basaline,method = "BH"),pvalues.activity.tetR.adaptive,p.adjust(pvalues.activity.tetR.adaptive,method = "BH"))
colnames(ttest.activities.matrix)[c(13:16)]<-c("p.value.baseline","adj.p.value.baseline","p.value.adaptive","adj.p.value.adaptive")
#Check change in activity of the 25 TFs previously identified by NetSurgeon
print(cbind(convert.locus.to.gene.name(table1[,"Locus.tag"]),round(ttest.activities.matrix[as.character(table1[,"Locus.tag"]),13:16],digits=4)))
             p.value.baseline adj.p.value.baseline p.value.adaptive adj.p.value.adaptive
b0080 "fruR" "0.4182"         "0.5933"             "0.0642"         "0.1186"            
b0413 "nrdR" "0.3079"         "0.4878"             "0.0016"         "0.0142"            
b0846 "ybjK" "0.0274"         "0.1738"             "0.0342"         "0.0758"            
b0889 "lrp"  "0.0096"         "0.0979"             "0.0097"         "0.0347"            
b0995 "torR" "5e-04"          "0.0286"             "0.3503"         "0.407"             
b1130 "phoP" "0.0678"         "0.2446"             "0.2795"         "0.3311"            
b1237 "hns"  "0.0305"         "0.1738"             "0.0093"         "0.0343"            
b1303 "pspF" "0.0043"         "0.0757"             "3e-04"          "0.0079"            
b1531 "marA" "0"              "0.0047"             "0.5063"         "0.5529"            
b1594 "dgsA" "0.624"          "0.7538"             "0.0063"         "0.0286"            
b1658 "purR" "0.2"            "0.3896"             "0.5076"         "0.5529"            
b1921 "fliZ" "0.0152"         "0.1424"             "0.3155"         "0.3701"            
b2217 "rcsB" "0.7908"         "0.8463"             "0.1533"         "0.2078"            
b2741 "rpoS" "0.0722"         "0.2446"             "0.0081"         "0.0318"            
b2980 "glcC" "0.0682"         "0.2446"             "0.04"           "0.0814"            
b3405 "ompR" "0.0655"         "0.2446"             "0.1112"         "0.1696"            
b3418 "malT" "0.7271"         "0.8003"             "0.0215"         "0.0546"            
b3512 "gadE" "0.0011"         "0.0431"             "0.0016"         "0.0142"            
b3934 "cytR" "0.0291"         "0.1738"             "0.0013"         "0.0136"            
b3973 "birA" "0.2412"         "0.4445"             "0.0574"         "0.1129"            
b4062 "soxS" "0.0225"         "0.1738"             "0.0209"         "0.0541"            
b4116 "adiY" "0.0078"         "0.0916"             "8e-04"          "0.0108"            
b4396 "rob"  "0.0708"         "0.2446"             "0.0282"         "0.0673"            
b4401 "arcA" "0.8351"         "0.8768"             "0.0074"         "0.0309"            
b4498 "gatR" "0.616"          "0.7538"             "0.0119"         "0.0377"            

2.3 Fig. 2B - Fold change of selected TF regulons

#define matrix with (average) fold-change values with respect to untreated WT
handel.foldchange.matrix<-handel.average.expression[,2:4]-handel.average.expression[,1]
#function to compute significance of fold-change of a given set of genes vs random selection
    permutation.function<-function(true.genes,column.of.fold.change.matrix)
    {
      #number of random gene sampling
      N=10000
      true.average.fold.change<-mean(handel.foldchange.matrix[true.genes,column.of.fold.change.matrix])
      random.compilation<-c()
    for(n in 1:N)
    {
      random.fold.change<-handel.foldchange.matrix[sample(1:nrow(handel.foldchange.matrix),length(true.genes)),column.of.fold.change.matrix]
      random.compilation<-c(random.compilation,mean(random.fold.change))
    }
      #conservative p-value estimation (minimum of one-tailed vs two-tailed test)
      estimated.pvalue<-min(c(length(which(random.compilation >= true.average.fold.change))/N,
                              length(which(random.compilation <= true.average.fold.change))/N,
                              length(which(abs(random.compilation)>=abs(true.average.fold.change)))))
      #return estimated p-value
      estimated.pvalue
    }
#generate boxplots for selected TFs (predicted as differentially active based on network analyses above)    
selected.tfs<-c("arcA","marA","gadE")
for(tf.name in selected.tfs)
{
  tf.locus<-translate.gene.name.to.locus(tf.name)
  if(tf.name=="arcA")
  {
   #focus on ArcA repressed genes 
   #ArcA is mainly a repressor: it represses 73.2% of its targets
   #furthermore, 80% of ArcA DE target genes are repressed by ArcA
   current.regulon.repression<-names(which(final.trn.network[,tf.locus]<0))
   #focus on DEGs (either in the TetR basaline or adaptive response)
   current.regulon.repression<-intersect(current.regulon.repression,tetR.DEGs)
   #fold-change matrix with DE target genes
   temporal.fold.change.matrix<-rbind(cbind(handel.foldchange.matrix[current.regulon.repression,1],rep("WT(+)",length(current.regulon.repression))),
                           cbind(handel.foldchange.matrix[current.regulon.repression,2],rep("TetR(-)",length(current.regulon.repression))),
                           cbind(handel.foldchange.matrix[current.regulon.repression,3],rep("TetR(+)",length(current.regulon.repression))))
    temporal.fold.change.matrix<-as.data.frame(temporal.fold.change.matrix)
    #define column names
    colnames(temporal.fold.change.matrix)<-c("Expression","Strain")
    temporal.fold.change.matrix$Expression<-as.numeric(as.vector(temporal.fold.change.matrix$Expression))
    temporal.fold.change.matrix$Strain<-factor(temporal.fold.change.matrix$Strain,levels = c("WT(+)","TetR(-)","TetR(+)"),ordered = TRUE)
    #create barplot with ggplot
    barplot.arcA <- ggplot(temporal.fold.change.matrix, aes(x=Strain, y=Expression,fill=Strain)) + 
      geom_boxplot(color="red")+ theme(text = element_text(size=24))
    print(barplot.arcA+scale_fill_manual(values=rep("white",3)) + 
    ggtitle(paste(tf.name,"--|",length(current.regulon.repression),"genes",sep=" ")))
    #run random permutation test for each comparison (e.g., WT+TET vs WT-TET, TetR-TET vs WT-TET, etc.)
    print(paste(tf.name,"-WT+TET vs WT-TET:",permutation.function(current.regulon.repression,1),sep=""))
    print(paste(tf.name,"-TetR-TET vs WT-TET:",permutation.function(current.regulon.repression,2),sep=""))
    print(paste(tf.name,"-TetR+TET vs WT-TET:",permutation.function(current.regulon.repression,3),sep=""))
  }
  #if TF is MarA or GadE
  #both MarA and GadE mainly act as activators (i.e., positively regulate >79% of their target genes)
  else
  {
  current.regulon.activation<-names(which(final.trn.network[,tf.locus]>0))
  if(length(current.regulon.activation)>0)
    {
   #focus on DEGs (either in the TetR basaline or adaptive response)
   current.regulon.activation<-intersect(current.regulon.activation,tetR.DEGs)
   #fold-change matrix with DE target genes
   temporal.fold.change.matrix<-rbind(cbind(handel.foldchange.matrix[current.regulon.activation,1],rep("WT(+)",length(current.regulon.activation))),
                           cbind(handel.foldchange.matrix[current.regulon.activation,2],rep("TetR(-)",length(current.regulon.activation))),
                           cbind(handel.foldchange.matrix[current.regulon.activation,3],rep("TetR(+)",length(current.regulon.activation))))
  
    temporal.fold.change.matrix<-as.data.frame(temporal.fold.change.matrix)
    colnames(temporal.fold.change.matrix)<-c("Expression","Strain")
    temporal.fold.change.matrix$Expression<-as.numeric(as.vector(temporal.fold.change.matrix$Expression))
    temporal.fold.change.matrix$Strain<-factor(temporal.fold.change.matrix$Strain,levels = c("WT(+)","TetR(-)","TetR(+)"),ordered = TRUE)
    #create barplot with ggplot
    barplot.activation <- ggplot(temporal.fold.change.matrix, aes(x=Strain, y=Expression,fill=Strain)) + 
      geom_boxplot(color="green")+ theme(text = element_text(size=24))
    print(barplot.activation+scale_fill_manual(values=rep("white",3)) +  ggtitle(paste(tf.name,"-->",length(current.regulon.activation),"genes",sep=" "))) 
  }
    #run random permutation test for each comparison (e.g., WT+TET vs WT-TET, TetR-TET vs WT-TET, etc.)
     print(paste(tf.name,"-WT+TET vs WT-TET:",permutation.function(current.regulon.activation,1),sep=""))
    print(paste(tf.name,"-TetR-TET vs WT-TET:",permutation.function(current.regulon.activation,2),sep=""))
    print(paste(tf.name,"-TetR+TET vs WT-TET:",permutation.function(current.regulon.activation,3),sep=""))
  }
}
[1] "arcA-WT+TET vs WT-TET:0.3709"
[1] "arcA-TetR-TET vs WT-TET:0.0972"
[1] "arcA-TetR+TET vs WT-TET:0"
[1] "marA-WT+TET vs WT-TET:0.3962"
[1] "marA-TetR-TET vs WT-TET:0"
[1] "marA-TetR+TET vs WT-TET:8e-04"
[1] "gadE-WT+TET vs WT-TET:0"
[1] "gadE-TetR-TET vs WT-TET:0"
[1] "gadE-TetR+TET vs WT-TET:0"

2.3 Evaluating overlap between DEGs in TetR adaptive response and arcA KO in anaerobic growth (GEO accession ID: GSE1107)

#transcriptional data for arcA KO was sourced from Covert et al. (Nature 2004)
arcA.ko.matrix.covert<-read.csv("../Data/Differential_expression_analysis/GEO_Covert2004/arcA_ko_Covert2004.csv",header=T,row.names = 1)
#select replicates for WT and arcA KO in anaerobic condition
arcA.ko.matrix.covert<-arcA.ko.matrix.covert[,c("ana_wt1","ana_wt2","ana_wt3","ana_wt4","ana_arcA1","ana_arcA2","ana_arcA3")]
#rename columns
colnames(arcA.ko.matrix.covert)<-c("anaerobic_wt1","anaerobic_wt2","anaerobic_wt3","anaerobic_wt4","anaerobic_arcA1","anaerobic_arcA2","anaerobic_arcA3")
#read microarray probes to loci map
arcA.microarray.probes.loci.map<-read.csv("../Data/Differential_expression_analysis/GEO_Covert2004/arcA_covert2004_probes_gene_map.csv")
#filter out those genes not included in the expression matrix for WT and TetR previously analyzed
arcA.microarray.probes.loci.map<-arcA.microarray.probes.loci.map[arcA.microarray.probes.loci.map$ORF %in% rownames(handel.normalized.matrix),]
#this will be the final matrix with locus tags as rownames
final.arcA.ko.matrix.covert<-c()
#store set of genes present in the resulting expression matrix
genes.included.in.covert.data<-c()
#change probe names to loci
for(g in 1:nrow(arcA.microarray.probes.loci.map))
{
  current.gene<-as.character(arcA.microarray.probes.loci.map$ORF[g])
  genes.included.in.covert.data<-c(genes.included.in.covert.data,current.gene)
  current.gene.position<-grep(current.gene,rownames(arcA.ko.matrix.covert))
  final.arcA.ko.matrix.covert<-rbind(final.arcA.ko.matrix.covert,arcA.ko.matrix.covert[current.gene.position,])
}
rownames(final.arcA.ko.matrix.covert)<-genes.included.in.covert.data
#log2 transform the microarray data
final.arcA.ko.matrix.covert<-log2(final.arcA.ko.matrix.covert)
#perform differential expression analysis (as previously done above)
arcA.ko.response.covert<-bayesT(final.arcA.ko.matrix.covert,numC = 4,numE = 3,conf = 7,doMulttest = T)
#DEGs due to arcA deletion
arcA.degs.covert<-rownames(arcA.ko.response.covert)[which(arcA.ko.response.covert$BH < 0.05 & abs(arcA.ko.response.covert$meanC - arcA.ko.response.covert$meanE)>1)]
#define overlap between DEGs in arcA KO and TetR response to tetracycline
overlapping.DEGs<-intersect(arcA.degs.covert,tetR.response.degs)
#evalute overlap significance with hypergeometric test 
overlap.pvalue<-phyper(length(overlapping.DEGs)-1,length(arcA.degs.covert),nrow(arcA.ko.response.covert)-length(arcA.degs.covert),length(intersect(tetR.response.degs,rownames(arcA.ko.response.covert))),lower.tail = F)
print(paste("Overlap p-value=",overlap.pvalue,sep=""))
[1] "Overlap p-value=5.46797704435238e-12"

3.1 Fig 3A (initial analysis of barcode sequencing data of genome-wide single gene KO library growth competition assays)

#read counts per design for TetR KO library (4 biological replicates per time point)
#this is the output of the InscriptaResolver  software 
tetR.ko.library.reads<-read.csv("../Data/KO_library_competition/raw_ko_count_data/TetR/a05h/a05h_design_report.csv",header=T)
#define unique samples (i.e., combinations of strain x replicate x treatment x time point)
#the following notation was used to label the samples: strain (tetR or wt)-K(for KO){a,b,c,d}(corresponding to the biological replicate)-'plus' or 'minus' tetracycline - {1,2,3} corresponding to the growth cycle (i.e., T1, T2, T3)
#0-plusTet and 0-minusTet correspond to T0 and they are the same sample (eg, TetR-Ka-minusTet is the same as TetR-Ka-0-plusTet) 
#T0 samples were duplicated when processing the data to facilitate (treatment-specific) downstream analyses   
tetR.ko.library.samples<-unique(tetR.ko.library.reads$SampleName)
#define KO designs
tetR.ko.library.designs<-unique(tetR.ko.library.reads$DesignId)
#create read count matrix that includes a column with the name of the gene associated with each KO design
#tetR.ko.library.count.matrix<-matrix(ncol=length(tetR.ko.library.samples)+1,nrow=length(tetR.ko.library.designs),0,
#                             dimnames = list(tetR.ko.library.designs,c("gene",tetR.ko.library.samples)))
#loop to fill out the count matrix
#for(s in tetR.ko.library.samples)
#{
#  print(s)
#  for(d in tetR.ko.library.designs)
#  {
#    current.position<-which(tetR.ko.library.reads$SampleName==s & tetR.ko.library.reads$DesignId==d)
#    current.count<-tetR.ko.library.reads[current.position,"DesignCount"]
#    tetR.ko.library.count.matrix[as.character(d),s]<- current.count
#    tetR.ko.library.count.matrix[as.character(d),"gene"]<-tetR.ko.library.reads[current.position,"Design_TargetName"]
#  }
#}
#tetR.ko.library.count.matrix.with.gene.info<-tetR.ko.library.count.matrix
#load previously compiled (with code shown above) TetR KO library read count matrix 
load("../Data/KO_library_competition/processed_count_data/tetR.ko.library.count.matrix.with.gene.info.RData")
#re-organize columns (ie, sample replicates)
tetR.ko.read.counts<-tetR.ko.library.count.matrix.with.gene.info[,c(10,2,26,18,12,4,28,20,13,5,29,21,14,6,30,22,15,7,31,23,16,8,32,24,17,9,33,25)]
#change column names to a simpler notation: Cycle-(+/-)TET-replicate{a,b,c,d}
colnames(tetR.ko.read.counts)<-paste(rep(c("C0","C1-TET-","C2-TET-","C3-TET-","C1+TET-","C2+TET-","C3+TET-"),each=4),letters[1:4],sep="")
#Ci indicates cycle # i in the competition assay. This means that C0=t0, C1=t1, etc.
#remove the column with gene names to create a new matrix that only contains numeric values
tetR.ko.read.counts.numeric<-c()
for(c in 1:ncol(tetR.ko.read.counts))
{
  tetR.ko.read.counts.numeric<-cbind(tetR.ko.read.counts.numeric,as.numeric(tetR.ko.read.counts[,c]))
}
colnames(tetR.ko.read.counts.numeric)<-colnames(tetR.ko.read.counts)
rownames(tetR.ko.read.counts.numeric)<-rownames(tetR.ko.read.counts)
#repeat process for WT KO library
#read counts per design for WT KO libraries (4 biological replicates per time point)
#this is the output of the InscriptaResolver  software
wt.ko.library.reads<-read.csv("../Data/KO_library_competition/raw_ko_count_data/WT/a05h/a05h_design_report.csv",header=T)
#define unique samples (with same notation used for the TetR KO library)
wt.ko.library.samples<-unique(wt.ko.library.reads$SampleName)
#define KO designs
wt.ko.library.designs<-unique(wt.ko.library.reads$DesignId)
#create read count matrix that includes a column with the name of the gene associated with each KO design
#wt.ko.library.count.matrix<-matrix(ncol=length(wt.ko.library.samples)+1,nrow=length(wt.ko.library.designs),0,
#                           dimnames = list(as.character(wt.ko.library.designs),c("gene",wt.ko.library.samples)))
#loop to fill out the count matrix
#for(s in wt.ko.library.samples)
#{
#  print(s)
#  for(d in wt.ko.library.designs)
#  {
#  current.position<-which(wt.ko.library.reads$SampleName==s & wt.ko.library.reads$DesignId==d)
#  current.count<-wt.ko.library.reads[current.position,"DesignCount"]
#  wt.ko.library.count.matrix[as.character(d),s]<- current.count
#  wt.ko.library.count.matrix[as.character(d),"gene"]<-wt.ko.library.reads[current.position,"Design_TargetName"]
#  }
#}
#wt.ko.library.count.matrix.with.gene.info<-wt.ko.library.count.matrix
#load previously compiled WT KO library read count matrix
load("../Data/KO_library_competition/processed_count_data/wt.ko.library.count.matrix.with.gene.info.RData")
#re-organize columns (ie, sample replicates)
wt.ko.read.counts<-wt.ko.library.count.matrix.with.gene.info[,c(10,2,26,18,12,4,28,20,13,5,29,21,14,6,30,22,15,7,31,23,16,8,32,24,17,9,33,25)]
#change column names using a new simpler notation: Cycle-(+/-)TET-replicate{a,b,c,d}
colnames(wt.ko.read.counts)<-colnames(tetR.ko.read.counts)
#remove the gene column to create a new matrix that only contains numeric values
wt.ko.read.counts.numeric<-c()
for(c in 1:ncol(wt.ko.read.counts))
{
  wt.ko.read.counts.numeric<-cbind(wt.ko.read.counts.numeric,as.numeric(wt.ko.read.counts[,c]))
}
colnames(wt.ko.read.counts.numeric)<-colnames(wt.ko.read.counts)
rownames(wt.ko.read.counts.numeric)<-rownames(wt.ko.read.counts)
#define depleted (ie, undetected) KO designs at each time point
#a KO design was considered not detected at a time point of interest when all four biological replicates had less than 10 reads for the corresponding KO design 
#initialize list to store KO designs labeled as depleted in TetR library
tetR.depleted.designs.time.series<-NULL
tetR.depleted.designs.time.series[c("T0","T1(-)","T2(-)","T3(-)","T1(+)","T2(+)","T3(+)")]<-list(NULL)
#define vector with total number of detected KO designs per sample/time point
tetR.non.depleted.designs.vector<-c()
#a loop to define depleted KO designs at each point
for(tetR.sample in 1:7)
{
  depleted.ko.designs.current.sample<-c()
  #the designs '500955653' and '500955654' are excluded from this analysis because they were used as internal controls and they are not associated with any gene
  for(ko.design in setdiff(tetR.ko.library.designs,c("500955653","500955654")))
  {
    if(max(tetR.ko.read.counts.numeric[as.character(ko.design),((4*tetR.sample)-3):(4*tetR.sample)])<10)
  {
    depleted.ko.designs.current.sample<-c(depleted.ko.designs.current.sample,ko.design)
  }
  }
  tetR.depleted.designs.time.series[[tetR.sample]]<-depleted.ko.designs.current.sample
  tetR.non.depleted.designs.vector<-c(tetR.non.depleted.designs.vector,8271-length(depleted.ko.designs.current.sample))
}
names(tetR.non.depleted.designs.vector)<-names(tetR.depleted.designs.time.series)
#same analysis for WT
#initialize list to store KO designs labeled as depleted in WT library
wt.depleted.designs.time.series<-NULL
wt.depleted.designs.time.series[c("T0","T1(-)","T2(-)","T3(-)","T1(+)","T2(+)","T3(+)")]<-list(NULL)
#define vector with total number of detected KO designs per sample/time point
wt.non.depleted.designs.vector<-c()
for(wt.sample in 1:7)
{
  depleted.designs.current.sample<-c()
  for(ko.design in setdiff(wt.ko.library.designs,c("500955653","500955654")))
  {
    if(max(wt.ko.read.counts.numeric[as.character(ko.design),((4*wt.sample)-3):(4*wt.sample)])<10)
  {
    depleted.designs.current.sample<-c(depleted.designs.current.sample,ko.design)
  }
  }
  wt.depleted.designs.time.series[[wt.sample]]<-depleted.designs.current.sample
  wt.non.depleted.designs.vector<-c(wt.non.depleted.designs.vector,8271-length(depleted.designs.current.sample))
}
names(wt.non.depleted.designs.vector)<-names(wt.depleted.designs.time.series)
#create left panel of Fig. 3A
par(mfrow=c(1,2))
#plot number of detected KO designs for TetR(-TET)
plot(x=0:3,y=tetR.non.depleted.designs.vector[1:4],type="o",xlab="Cycle",
     ylab="# mutant designs",col="red",ylim=c(5000,8050),lty=2,pch=20,cex=1.5,cex.lab=1.5, cex.axis=1.5)
#add number of detected KO designs for TetR(+TET)
points(x=0:3,y=tetR.non.depleted.designs.vector[c(1,5:7)],type="o",col="red4",pch=20)
#add number of detected KO designs for WT(-TET)
points(x=0:3,y=wt.non.depleted.designs.vector[1:4],type="o",col="blue",lty=2,pch=20)
#add number of detected KO designs for WT(+TET)
points(x=0:3,y=wt.non.depleted.designs.vector[c(1,5:7)],type="o",col="blue4",pch=20)
legend(x=0,y=6800,legend=c("TetR(+)","TetR(-)","WT(+)","WT(-)"),cex=1.1,col=c("red4","red","blue4","blue"),pch=rep(20,4),box.lwd = 0,lty=c(1,2,1,2))
#perform similar analysis to identify genes whose KOs were undetectable
#a gene was considered undetected (ie,depleted) if its two KO designs were labeled as depleted in the previous analysis
#initialize list to store name of genes labeled as depleted in TetR library
tetR.depleted.genes<-NULL
tetR.depleted.genes[c("T0","T1(-)","T2(-)","T3(-)","T1(+)","T2(+)","T3(+)")]<-list(NULL)
#define vector with total number of detected genes per sample/time point
tetR.non.depleted.genes.count.vector<-c()
for(tetR.sample in 1:7)
{
  #KO designs labeled as depleted in current sample
  depleted.designs.current.sample<-tetR.depleted.designs.time.series[[tetR.sample]]
  #count number of depleted designs associated with each gene
  depleted.design.to.gene.map<-tetR.ko.library.count.matrix.with.gene.info[which(rownames(tetR.ko.library.count.matrix.with.gene.info)%in%depleted.designs.current.sample),"gene"]
  temporal.gene.count.table<-table(depleted.design.to.gene.map)
  #define set of depleted genes
  tetR.depleted.genes[[tetR.sample]]<-names(which(temporal.gene.count.table==2))
  tetR.non.depleted.genes.count.vector<-c(tetR.non.depleted.genes.count.vector,4153-length(tetR.depleted.genes[[tetR.sample]]))
}
#initialize list to store names of genes labeled as depleted in WT library
wt.depleted.genes<-NULL
wt.depleted.genes[c("T0","T1(-)","T2(-)","T3(-)","T1(+)","T2(+)","T3(+)")]<-list(NULL)
#define vector with total number of detected genes per sample/time point
wt.non.depleted.genes.count.vector<-c()
for(wt.sample in 1:7)
{
  #KO designs labeled as depleted in current sample
  depleted.designs.current.sample<-wt.depleted.designs.time.series[[wt.sample]]
  #count number of depleted designs associated with each gene
  depleted.design.to.gene.map<-wt.ko.library.count.matrix.with.gene.info[which(rownames(wt.ko.library.count.matrix.with.gene.info)%in%depleted.designs.current.sample),"gene"]
  temporal.gene.count.table<-table(depleted.design.to.gene.map)
  #define set of depleted genes
  wt.depleted.genes[[wt.sample]]<-names(which(temporal.gene.count.table==2))
  wt.non.depleted.genes.count.vector<-c(wt.non.depleted.genes.count.vector,4153-length(wt.depleted.genes[[wt.sample]]))
}
#create right panel of Fig. 3A
#plot number of detected genes for TetR(-TET)
plot(x=0:3,y=tetR.non.depleted.genes.count.vector[1:4],type="o",xlab="Cycle",
     ylab="# detected genes",col="red",ylim=c(3200,4120),lty=2,pch=20,cex=1.5,cex.lab=1.5, cex.axis=1.5)
#add number of detected genes for TetR(+TET)
points(x=0:3,y=tetR.non.depleted.genes.count.vector[c(1,5:7)],type="o",col="red4",pch=20)
#add number of detected genes for WT(-TET)
points(x=0:3,y=wt.non.depleted.genes.count.vector[1:4],type="o",col="blue",lty=2,pch=20)
#add number of detected genes for WT(+TET)
points(x=0:3,y=wt.non.depleted.genes.count.vector[c(1,5:7)],type="o",col="blue4",pch=20)
legend(x=0,y=3800,legend=c("TetR(+)","TetR(-)","WT(+)","WT(-)"),cex=1.1,col=c("red4","red","blue4","blue"),pch=rep(20,4),box.lwd = 0,lty=c(1,2,1,2))

#print summary table
output.summary<-cbind(tetR.non.depleted.designs.vector,tetR.non.depleted.genes.count.vector,wt.non.depleted.designs.vector,wt.non.depleted.genes.count.vector)
colnames(output.summary)<-c("TetR-detected KO designs","TetR-detected genes","WT-detected KO designs","WT-detected genes")
print(output.summary)
      TetR-detected KO designs TetR-detected genes WT-detected KO designs WT-detected genes
T0                        7993                4106                   7908              4085
T1(-)                     7911                4084                   7859              4069
T2(-)                     7845                4066                   7814              4058
T3(-)                     7842                4066                   7789              4054
T1(+)                     7933                4087                   7868              4075
T2(+)                     7465                3973                   7887              4078
T3(+)                     5359                3343                   7543              3978

3.2 Create Fig. 3B

#write CSV file with gene name and locus tag of all genes identified as depleted in the last time point (T3) of TetR+TET competition experiment due to tetracycline (this set does not include genes not detected at T0 or T3-TET)
#this file is the input for DAVID (https://david.ncifcrf.gov/home.jsp) functional annotation clustering analysis
#genes.depleted.in.tetR.due.to.tet<-setdiff(tetR.depleted.genes[["T3(+)"]],union(tetR.depleted.genes[["T0"]],tetR.depleted.genes[["T3(-)"]]))
#write.csv(file="../Data/KO_library_competition/processed_count_data/tetR_depleted_genes_t3_due_to_tetracycline.csv",cbind(genes.depleted.in.tetR.due.to.tet,translate.gene.name.to.locus(genes.depleted.in.tetR.due.to.tet)))
#create barplot for Fig 3B (using DAVID output)
par(mfrow=c(1,2))
plot.new()
barplot(c(116,74,28,27,24,18,16,11,11)
          ,cex.lab=1.25,cex.axis=1.25,cex.names = 1,xlab="# genes",
names=c("Nucleotide/ATP binding","Ribosome/Translation/rRNA-binding","LPS biosynthesis","Cell division","Cell wall org./cell shape","Biosynthesis of nucleotide sugars","DNA replication","Ribosome biogenesis","Ubiquinone biosynthesis"),col=rainbow(9),las=2,horiz = T,xlim=c(0,120),main="Fig. 3B")

3.3 Load and process ALDEx2 output

#the script below runs ALDEx2 and generates relevant outputs (eg, T1 vs T0 with and without tetracycline in the TetR and WT libraries)
#source("aldex2_analysis.R")
#load ALDEx2 output
load("../Data/KO_library_competition/processed_count_data/ALDEx2_output.RData")
#notation of the ALDEx2 output: strain(tetR/wt).ko.iqlr(for inter-quartile log ratio).c0(this is T0).c#i(where i is 1 or 2 for T1 or T2).plus/minus(tetracycline treatment)
#function to define genes whose deletion impact fitness 
#that is genes for which all of their non-depleted designs were over- or under-represented in the ALDEx2 test
define.high.confindence.genes<-function(design.set,aldex.output.matrix,read.count.matrix)
{
  output<-c()
  #we need to define the genes associated with the differentially abundant designs (design.set defined using ALDEx2)
  input.design.to.gene.map<-read.count.matrix[which(rownames(read.count.matrix)%in%design.set),"gene"]
  genes.in.selected.designs<-unique(input.design.to.gene.map)
  #we also need to define how many designs were associated with each gene in ALDEx2 input matrix (rownames of the aldex.output.matrix)
  full.matrix.design.to.gene.map<-read.count.matrix[which(rownames(read.count.matrix)%in%rownames(aldex.output.matrix)),"gene"]
  #loop to evaluate which genes were differentially abundant 
  for(g in genes.in.selected.designs)
  {
    if(length(which(input.design.to.gene.map==g))==length(which(full.matrix.design.to.gene.map==g)))
    {
      output<-c(output,g)
    }
  }
  output
}  
#############################################################
#adjusted p-value (qvalue) and ALDEx2-estimated effect thresholds used in the analysis
qval.threshold<-0.1
effect.threshold<-2
#process ALDEx2 output for TetR+TET (T1) vs TetR (T0) (tetR.ko.iqlr.c0.c1.plus)
#identify under-represented (deleterious) KO designs
tetR.deleterious.feautures.c0.c1.plus<-rownames(tetR.ko.iqlr.c0.c1.plus)[which(tetR.ko.iqlr.c0.c1.plus$we.eBH < qval.threshold & tetR.ko.iqlr.c0.c1.plus$wi.eBH < qval.threshold &  tetR.ko.iqlr.c0.c1.plus$effect < -1*effect.threshold)]
#define genes whose deletions were deleterious
tetR.deleterious.deletions.c0.c1.plus.high.confidence<-define.high.confindence.genes(design.set =tetR.deleterious.feautures.c0.c1.plus, aldex.output.matrix = tetR.ko.iqlr.c0.c1.plus,read.count.matrix = tetR.ko.library.count.matrix.with.gene.info)
#identify over-represented (beneficial) KO designs
tetR.beneficial.feautures.c0.c1.plus<-rownames(tetR.ko.iqlr.c0.c1.plus)[which(tetR.ko.iqlr.c0.c1.plus$we.eBH < qval.threshold  & tetR.ko.iqlr.c0.c1.plus$wi.eBH < qval.threshold  & tetR.ko.iqlr.c0.c1.plus$effect > effect.threshold)]
#define genes whose deletions were beneficial
tetR.beneficial.deletions.c0.c1.plus.high.confidence<-define.high.confindence.genes(design.set =tetR.beneficial.feautures.c0.c1.plus, aldex.output.matrix = tetR.ko.iqlr.c0.c1.plus,read.count.matrix = tetR.ko.library.count.matrix.with.gene.info)
#remove genes with KO designs labeled as beneficial AND deleterious
tetR.deleterious.deletions.c0.c1.plus.final<-setdiff(tetR.deleterious.deletions.c0.c1.plus.high.confidence,tetR.beneficial.deletions.c0.c1.plus.high.confidence)
tetR.beneficial.deletions.c0.c1.plus.final<-setdiff(tetR.beneficial.deletions.c0.c1.plus.high.confidence,tetR.deleterious.deletions.c0.c1.plus.high.confidence)
#############################################################
#process ALDEx2 output for TetR+TET (T2) vs TetR (T0) (tetR.ko.iqlr.c0.c2.plus)
#identify under-represented (deleterious) KO designs 
tetR.deleterious.feautures.c0.c2.plus<-rownames(tetR.ko.iqlr.c0.c2.plus)[which(tetR.ko.iqlr.c0.c2.plus$we.eBH < qval.threshold  & tetR.ko.iqlr.c0.c2.plus$wi.eBH < qval.threshold & tetR.ko.iqlr.c0.c2.plus$effect < -1*effect.threshold)]
#identify genes whose deletions were deleterious
tetR.deleterious.deletions.c0.c2.plus.high.confidence<-define.high.confindence.genes(design.set =tetR.deleterious.feautures.c0.c2.plus, aldex.output.matrix = tetR.ko.iqlr.c0.c2.plus,read.count.matrix = tetR.ko.library.count.matrix.with.gene.info)
#identify over-represented (beneficial) KO designs
tetR.beneficial.feautures.c0.c2.plus<-rownames(tetR.ko.iqlr.c0.c2.plus)[which(tetR.ko.iqlr.c0.c2.plus$we.eBH < qval.threshold & tetR.ko.iqlr.c0.c2.plus$wi.eBH < qval.threshold & tetR.ko.iqlr.c0.c2.plus$effect > effect.threshold)]
#identify genes whose deletions were beneficial
tetR.beneficial.deletions.c0.c2.plus.high.confidence<-define.high.confindence.genes(design.set =tetR.beneficial.feautures.c0.c2.plus, aldex.output.matrix = tetR.ko.iqlr.c0.c2.plus,read.count.matrix = tetR.ko.library.count.matrix.with.gene.info)
#remove genes with mutant designs labeled as beneficial AND deleterious
tetR.deleterious.deletions.c0.c2.plus.final<-setdiff(tetR.deleterious.deletions.c0.c2.plus.high.confidence,tetR.beneficial.deletions.c0.c2.plus.high.confidence)
tetR.beneficial.deletions.c0.c2.plus.final<-setdiff(tetR.beneficial.deletions.c0.c2.plus.high.confidence,tetR.deleterious.deletions.c0.c2.plus.high.confidence)
#consolidate results for the TetR library
#gene deletions with opposite effects at different time points were not considered
tetR.deleterious.aldex.compilation<-setdiff(union(tetR.deleterious.deletions.c0.c1.plus.final,tetR.deleterious.deletions.c0.c2.plus.final),union(tetR.beneficial.deletions.c0.c1.plus.final,tetR.beneficial.deletions.c0.c2.plus.final))
tetR.beneficial.aldex.compilation<-setdiff(union(tetR.beneficial.deletions.c0.c1.plus.final,tetR.beneficial.deletions.c0.c2.plus.final),union(tetR.deleterious.deletions.c0.c1.plus.final,tetR.deleterious.deletions.c0.c2.plus.final))
print(paste("TetR had",length(tetR.deleterious.aldex.compilation),"genes whose deletions were deleterious",sep=" "))
[1] "TetR had 308 genes whose deletions were deleterious"
print(paste("TetR had",length(tetR.beneficial.aldex.compilation),"genes whose deletions were beneficial",sep=" "))
[1] "TetR had 953 genes whose deletions were beneficial"
#zero KO designs were identified as differentially abundant at T1(-TET) or T2(-TET) vs T0
#############################################################
#process ALDEx2 output for WT+TET (T1) vs WT (T0) (wt.ko.iqlr.c0.c1.plus)
#identify under-represented (deleterious) KO designs
wt.deleterious.feautures.c0.c1.plus<-rownames(wt.ko.iqlr.c0.c1.plus)[which(wt.ko.iqlr.c0.c1.plus$we.eBH < qval.threshold & wt.ko.iqlr.c0.c1.plus$wi.eBH < qval.threshold & wt.ko.iqlr.c0.c1.plus$effect < -1*effect.threshold)]
#identify genes whose deletions were deleterious
wt.deleterious.deletions.c0.c1.plus.high.confidence<-define.high.confindence.genes(design.set =wt.deleterious.feautures.c0.c1.plus, aldex.output.matrix = wt.ko.iqlr.c0.c1.plus,read.count.matrix = wt.ko.library.count.matrix.with.gene.info)
#identify over-represented (beneficial) KO designs
wt.beneficial.feautures.c0.c1.plus<-rownames(wt.ko.iqlr.c0.c1.plus)[which(wt.ko.iqlr.c0.c1.plus$we.eBH < qval.threshold & wt.ko.iqlr.c0.c1.plus$wi.eBH < qval.threshold & wt.ko.iqlr.c0.c1.plus$effect > effect.threshold)]
#identify genes whose deletions were beneficial
wt.beneficial.deletions.c0.c1.plus.high.confidence<-define.high.confindence.genes(design.set =wt.beneficial.feautures.c0.c1.plus, aldex.output.matrix = wt.ko.iqlr.c0.c1.plus,read.count.matrix = wt.ko.library.count.matrix.with.gene.info)
#remove genes with mutant designs identified as both beneficial AND deleterious
wt.deleterious.deletions.c0.c1.plus.final<-setdiff(wt.deleterious.deletions.c0.c1.plus.high.confidence,wt.beneficial.deletions.c0.c1.plus.high.confidence)
wt.beneficial.deletions.c0.c1.plus.final<-setdiff(wt.beneficial.deletions.c0.c1.plus.high.confidence,wt.deleterious.deletions.c0.c1.plus.high.confidence)
#############################################################
#process ALDEx2 output for WT+TET (T2) vs WT (T0) (wt.ko.iqlr.c0.c2.plus)
#identify under-represented (deleterious) KO designs
wt.deleterious.feautures.c0.c2.plus<-rownames(wt.ko.iqlr.c0.c2.plus)[which(wt.ko.iqlr.c0.c2.plus$we.eBH < qval.threshold  & wt.ko.iqlr.c0.c2.plus$wi.eBH < qval.threshold  & wt.ko.iqlr.c0.c2.plus$effect < -1*effect.threshold )]
#identify genes whose deletions were deleterious
wt.deleterious.deletions.c0.c2.plus.high.confidence<-define.high.confindence.genes(design.set =wt.deleterious.feautures.c0.c2.plus, aldex.output.matrix = wt.ko.iqlr.c0.c2.plus,read.count.matrix = wt.ko.library.count.matrix.with.gene.info)
#identify over-represented (beneficial) KO designs
wt.beneficial.feautures.c0.c2.plus<-rownames(wt.ko.iqlr.c0.c2.plus)[which(wt.ko.iqlr.c0.c2.plus$we.eBH < qval.threshold  & wt.ko.iqlr.c0.c2.plus$wi.eBH < qval.threshold  & wt.ko.iqlr.c0.c2.plus$effect > effect.threshold)]
#identify genes whose deletions were beneficial
wt.beneficial.deletions.c0.c2.plus.high.confidence<-define.high.confindence.genes(design.set =wt.beneficial.feautures.c0.c2.plus, aldex.output.matrix = wt.ko.iqlr.c0.c2.plus,read.count.matrix = wt.ko.library.count.matrix.with.gene.info)
#remove genes with mutant designs identified as both beneficial AND deleterious
wt.deleterious.deletions.c0.c2.plus.final<-setdiff(wt.deleterious.deletions.c0.c2.plus.high.confidence,wt.beneficial.deletions.c0.c2.plus.high.confidence)
wt.beneficial.deletions.c0.c2.plus.final<-setdiff(wt.beneficial.deletions.c0.c2.plus.high.confidence,wt.deleterious.deletions.c0.c2.plus.high.confidence)
#consolidate results for the WT library
wt.deleterious.aldex.compilation<-union(wt.deleterious.deletions.c0.c1.plus.final,wt.deleterious.deletions.c0.c2.plus.final)
wt.beneficial.aldex.compilation<-union(wt.beneficial.deletions.c0.c1.plus.final,wt.beneficial.deletions.c0.c2.plus.final)
print(paste("WT had",length(wt.deleterious.aldex.compilation),"genes whose deletions were deleterious",sep=" "))
[1] "WT had 208 genes whose deletions were deleterious"
print(paste("WT had",length(wt.beneficial.aldex.compilation),"genes whose deletions were beneficial",sep=" "))
[1] "WT had 155 genes whose deletions were beneficial"

3.4 Fig. 3C

#plot profiles of changes in abundance (with respect to T0) for selected genes (one KO design per gene)
selected.genes<-c("atpA","frdC","acrZ","mdtA","uvrA","arcA","phoP","rpoS","cytR")
#corresponding KO designs (in the same order of the selected genes)
selected.designs<-c("6417560","6418918","6423156","6417461","6422556","6405971","6421304","6414543","6417292")
par(mfrow=c(3,3))
#loop to generate each subpanel
for(i in 1:length(selected.genes))
  {
    current.design<-selected.designs[i]
    current.gene<-selected.genes[i]
    #profile of abundance difference of current gene in  antibiotic-free TetR library
    tetR.untreated.vector<-c(0,tetR.ko.iqlr.c0.c1.minus[current.design,"diff.btw"],tetR.ko.iqlr.c0.c2.minus[current.design,"diff.btw"]) 
    #profile of abundance difference of current gene in  tetracycline-treated TetR library
    tetR.treated.vector<-c(0,tetR.ko.iqlr.c0.c1.plus[current.design,"diff.btw"],tetR.ko.iqlr.c0.c2.plus[current.design,"diff.btw"])
    #profile of abundance difference of current gene in  antibiotic-free WT library
    wt.untreated.vector<-c(0,wt.ko.iqlr.c0.c1.minus[current.design,"diff.btw"],wt.ko.iqlr.c0.c2.minus[current.design,"diff.btw"])
    #profile of abundance difference of current gene in  tetracycline-treated WT library
    wt.treated.vector<-c(0,wt.ko.iqlr.c0.c1.plus[current.design,"diff.btw"],wt.ko.iqlr.c0.c2.plus[current.design,"diff.btw"])
    #create plot for current gene
    plot(y=tetR.untreated.vector,x=0:2,col="red",lty=2,ylim=range(c(tetR.untreated.vector,tetR.treated.vector,wt.untreated.vector,wt.treated.vector),na.rm = T),main=paste(current.gene,current.design,sep="-"),type="o",ylab=expression(paste(Delta,"abundance (vs t0)")),xlab="Cycle",cex=1.1,cex.lab=1.1, cex.axis=1.1)
    points(y=tetR.treated.vector,x=0:2,col="red4",type="o")
    points(y=wt.treated.vector,x=0:2,col="blue4",type="o")
    points(y=wt.untreated.vector,x=0:2,col="blue",type="o",lty=2)
  }

3.5 Fig. S4

#create Fig. S4A
#compare genes whose deletion affect fitness on TetR and/or WT backgrounds
#comparison of genes associated with deleterious KO deletions
conserved.deleterious.genes<-intersect(wt.deleterious.aldex.compilation,tetR.deleterious.aldex.compilation)
tetR.unique.deleterious.genes<-setdiff(tetR.deleterious.aldex.compilation,wt.deleterious.aldex.compilation)
wt.unique.deleterious.genes<-setdiff(wt.deleterious.aldex.compilation,tetR.deleterious.aldex.compilation)
#comparison of genes associated with beneficial KO deletions
conserved.beneficial.genes<-intersect(wt.beneficial.aldex.compilation,tetR.beneficial.aldex.compilation)
tetR.unique.beneficial.genes<-setdiff(tetR.beneficial.aldex.compilation,wt.beneficial.aldex.compilation)
wt.unique.beneficial.genes<-setdiff(wt.beneficial.aldex.compilation,tetR.beneficial.aldex.compilation)
#compile name of genes that impact fitness in the WT and/or TetR strains during tetracycline treatment
differentially.abundant.gene.compilation<-unique(c(conserved.beneficial.genes,wt.unique.beneficial.genes,tetR.unique.beneficial.genes,conserved.deleterious.genes,wt.unique.deleterious.genes,tetR.unique.deleterious.genes))
#create matrix for heatmap
input.matrix.for.heatmap<-matrix(nrow=length(differentially.abundant.gene.compilation),ncol=2,dimnames = list(differentially.abundant.gene.compilation,c("WT","TetR")),0)
#fill out input matrix
#the notation is: +1 = beneficial deletion, -1 = deleterious deletion, 0 = neutral
for(gene in differentially.abundant.gene.compilation)
{
  #check if deletion of current gene is beneficial in the WT background
  if(gene %in% wt.beneficial.aldex.compilation)
  {
    input.matrix.for.heatmap[gene,"WT"]<-1
  }
  #check if deletion of current gene is deleterious in the WT background
  if(gene %in% wt.deleterious.aldex.compilation)
  {
    input.matrix.for.heatmap[gene,"WT"]<- -1
  }
  #check if deletion of current gene is beneficial in the TetR background
  if(gene %in% tetR.beneficial.aldex.compilation)
  {
    input.matrix.for.heatmap[gene,"TetR"]<-1
  }
  #check if deletion of current gene is deleterious in the WT background
  if(gene %in% tetR.deleterious.aldex.compilation)
  {
    input.matrix.for.heatmap[gene,"TetR"]<- -1
  }
}
pheatmap(input.matrix.for.heatmap,scale="none",color = colorRampPalette(rev(brewer.pal(3, "PiYG")) )(3)[3:1],cluster_rows=F,cluster_cols = F,fontsize = 5,angle_col = 90,legend=T, main="Fig. S4A",breaks =c(-1,-0.0001,0.0001,1),legend_breaks = c(-1,-0.0001,0.0001,1),legend_labels = c("-1","0","0","+1"),show_rownames=FALSE)
#create Fig. S4B 
#write CSV files with TetR-specific deleterious and beneficial gene deletions
#write.csv(file="../Data/KO_library_competition/processed_count_data/tetR_specific_beneficial_genes_082422.csv",cbind(translate.gene.name.to.locus(tetR.unique.beneficial.genes),tetR.unique.beneficial.genes))
#write.csv(file="../Data/KO_library_competition/processed_count_data/tetR_specific_deleterious_genes_082422.csv",cbind(translate.gene.name.to.locus(tetR.unique.deleterious.genes),tetR.unique.deleterious.genes))
#based on output from DAVID functional enrichment analysis
#create barplot 
par(mfrow=c(1,2))

plot.new()
barplot(c(40,29,13,6,9),cex.lab=1.1,cex.axis=1.1,cex.names = 1.1,xlab="Number of genes",
names=c("Fe/other ion transport","Pilus-cell adhesion","TCA","Enterobactin biosynthesis","Ubiquinone/other terpenoid-quinone biosynthesis"),col=c("#66c2a5","#fc8d62","#8da0cb","#e78ac3","#a6d854"),las=2,horiz = T,xlim=c(0,42),main="Fig. S4B")

#create Fig. S4C
#heatmap for TFs whose deletion affect fitness of TetR and/or WT
#define names of E. coli TFs 
ecoli.tfs<-convert.locus.to.gene.name(tf.names)
#manually update TF names to include gene name synonym used by InscriptaResolver
ecoli.tfs[which(ecoli.tfs=="rpiR")]<-"alsR"
ecoli.tfs[which(ecoli.tfs=="ycgE")]<-"bluR"
ecoli.tfs[which(ecoli.tfs=="ycfQ")]<-"comR"
ecoli.tfs[which(ecoli.tfs=="fruR")]<-"cra"
ecoli.tfs[which(ecoli.tfs=="yfhA")]<-"glrR"
ecoli.tfs[which(ecoli.tfs=="yjiE")]<-"hypT"
ecoli.tfs[which(ecoli.tfs=="matA")]<-"ecpR"
ecoli.tfs[which(ecoli.tfs=="chpR")]<-"mazE"
ecoli.tfs[which(ecoli.tfs=="dgsA")]<-"mlc"
ecoli.tfs[which(ecoli.tfs=="ygiT")]<-"mqsA"
ecoli.tfs[which(ecoli.tfs=="yfeT")]<-"murR"
ecoli.tfs[which(ecoli.tfs=="ycjZ")]<-"pgrR"
ecoli.tfs[which(ecoli.tfs=="ybjK")]<-"rcdA"
ecoli.tfs[which(ecoli.tfs=="ydcN")]<-"sutR"
ecoli.tfs[which(ecoli.tfs=="yehT")]<-"btsR"
ecoli.tfs[which(ecoli.tfs=="yqjI")]<-"nfeR"
#identify TFs whose deletion affect fitness of TetR and/or WT
differentially.abundant.tfs<-intersect(ecoli.tfs,differentially.abundant.gene.compilation)
#create matrix with changes in abundance (delta) with respect to T0 for selected TFs during tetracycline treatment
tf.deletion.delta.abundance.matrix<-c()
#vector to record order of TFs (important for next step)
order.of.tfs.in.matrix<-c()
#identify KO designs associated with differentially abundant TFs
tf.ko.designs<-rownames(tetR.ko.library.count.matrix.with.gene.info)[which(tetR.ko.library.count.matrix.with.gene.info[,"gene"]%in% differentially.abundant.tfs)]
#fill out tf.deletion.delta.abundance.matrix
for(d in tf.ko.designs)
{
    current.design.delta.abundance.profile<-cbind(wt.ko.iqlr.c0.c1.plus[d,"diff.btw"],wt.ko.iqlr.c0.c2.plus[d,"diff.btw"],tetR.ko.iqlr.c0.c1.plus[d,"diff.btw"],tetR.ko.iqlr.c0.c2.plus[d,"diff.btw"])
    tf.deletion.delta.abundance.matrix<-rbind(tf.deletion.delta.abundance.matrix,
                                              current.design.delta.abundance.profile)
    order.of.tfs.in.matrix<-c(order.of.tfs.in.matrix,tetR.ko.library.count.matrix.with.gene.info[d,"gene"])
}
#rename matrix using TF names
rownames(tf.deletion.delta.abundance.matrix)<-order.of.tfs.in.matrix
#re-order matrix rows by TF names
tf.deletion.delta.abundance.matrix<-tf.deletion.delta.abundance.matrix[order(rownames(tf.deletion.delta.abundance.matrix)),]
#compute mean difference in abundance for TFs with two KO designs
average.tf.deletion.delta.abundance.matrix<-c()
for(tf in unique(rownames(tf.deletion.delta.abundance.matrix)))
{
  current.tf.position<-which(rownames(tf.deletion.delta.abundance.matrix)==tf)
  if(length(current.tf.position)==2)
  {
    average.tf.deletion.delta.abundance.matrix<-rbind(average.tf.deletion.delta.abundance.matrix,colMeans(tf.deletion.delta.abundance.matrix[current.tf.position,],na.rm = T))
  }
  else
  {
    average.tf.deletion.delta.abundance.matrix<-rbind(average.tf.deletion.delta.abundance.matrix,tf.deletion.delta.abundance.matrix[current.tf.position,])
  }
}
rownames(average.tf.deletion.delta.abundance.matrix)<-unique(rownames(tf.deletion.delta.abundance.matrix))
#replace NAs (that occur for those time points in which a gene KOs were not detected) with a "20" value
average.tf.deletion.delta.abundance.matrix[which(is.na(average.tf.deletion.delta.abundance.matrix))]<-20
#add column names
colnames(average.tf.deletion.delta.abundance.matrix)<-c("WT.t1","WT.t2","TetR.t1","TetR.t2")
#define heatmap breaks
heatmap.breaks<-c(-10,-4,-2,-1,-0.5,0,0.5,1,2,4,10,20)
#generate heatmap
pheatmap(average.tf.deletion.delta.abundance.matrix,scale="none",color =c(colorRampPalette(rev(brewer.pal(10, "PiYG")) )(10)[10:1],"black"),
         cluster_rows=F,cluster_cols = F,fontsize = 5,angle_col = 90,
legend=T,breaks =heatmap.breaks,legend_breaks = heatmap.breaks,main="Fig. S4C")

3.6 Fig. S5

#plot profiles of changes in abundance (with respect to T0) for selected genes (one KO design per gene)
selected.genes<-c("menB","frdB","hybB","mdh")
#corresponding KO designs (in the same order of the selected genes)
selected.designs<-c("6419317","6416702","6418292","6419091")
#loop to generate each subpanel
par(mfrow=c(2,2))
for(i in 1:length(selected.genes))
{
  current.gene<-selected.genes[i]
  current.design<-selected.designs[i]
  #profile of abundance difference of current gene in  antibiotic-free TetR library
  tetR.untreated.vector<-c(0,tetR.ko.iqlr.c0.c1.minus[current.design,"diff.btw"],tetR.ko.iqlr.c0.c2.minus[current.design,"diff.btw"])
  #profile of abundance difference of current gene in  tetracycline-treated TetR library
  tetR.tetracycline.treated.vector<-c(0,tetR.ko.iqlr.c0.c1.plus[current.design,"diff.btw"],tetR.ko.iqlr.c0.c2.plus[current.design,"diff.btw"])
  #profile of abundance difference of current gene in  antibiotic-free WT library
  wt.untreated.vector<-c(0,wt.ko.iqlr.c0.c1.minus[current.design,"diff.btw"],wt.ko.iqlr.c0.c2.minus[current.design,"diff.btw"])
  #profile of abundance difference of current gene in  tetracycline-treated WT library
  wt.tetracycline.treated.vector<-c(0,wt.ko.iqlr.c0.c1.plus[current.design,"diff.btw"],wt.ko.iqlr.c0.c2.plus[current.design,"diff.btw"])
  #create plot for current gene
  plot(y=tetR.untreated.vector,x=0:2,col="red",lty=2,ylim=range(c(tetR.untreated.vector,tetR.tetracycline.treated.vector,wt.untreated.vector,wt.tetracycline.treated.vector),na.rm = T),main=paste(current.gene,current.design,sep="-"),type="o",ylab=expression(paste(Delta,"abundance (vs t0)")),xlab="Cycle",cex=1.1,cex.lab=1.1, cex.axis=1.1)
  points(y=tetR.tetracycline.treated.vector,x=0:2,col="red4",type="o")
  points(y=wt.untreated.vector,x=0:2,col="blue",type="o",lty=2)
  points(y=wt.tetracycline.treated.vector,x=0:2,col="blue4",type="o")
}

3.7 Evaluate overlap between TetR dropouts at T3 and ALDEx2 results

#identify genes labeled as undetectable at the end of the experiment with tetracycline
#exclude genes that were not detected at the beginning of the experiment (T0) and the end of the experiment with no tetracycline (T3-TET)
tetR.depleted.genes.due.to.tetracycline<-setdiff(tetR.depleted.genes[["T3(+)"]],union(tetR.depleted.genes[["T0"]],tetR.depleted.genes[["T3(-)"]]))
#overlap with TetR-specific genes with deleterious deletions
overlapping.genes<-intersect(tetR.depleted.genes.due.to.tetracycline,tetR.unique.deleterious.genes)
print(paste("There are",length(overlapping.genes),"genes in common",sep=" "))
[1] "There are 55 genes in common"
#perform hypergeometric test
#define gene universe. First, we need to identify which genes were included in the ALDEx2 comparisons for T1(+TET) vs T0 and T2(+TET) vs T0
aldex2.designs.included.in.comparisons<-union(rownames(tetR.ko.iqlr.c0.c1.plus),rownames(tetR.ko.iqlr.c0.c2.plus))
#remove two control KO designs not associated with any gene
aldex2.designs.included.in.comparisons<-setdiff(aldex2.designs.included.in.comparisons,c("500955653","500955654"))
#define the genes associated with the KO designs
gene.universe.for.test<-unique(tetR.ko.library.count.matrix.with.gene.info[aldex2.designs.included.in.comparisons,"gene"])
#run hypergeometric test
q<-length(overlapping.genes)
m<-length(intersect(gene.universe.for.test,tetR.depleted.genes.due.to.tetracycline))
n<-length(gene.universe.for.test)-m
k<-length(intersect(tetR.unique.deleterious.genes,gene.universe.for.test))
pvalue.overlap<-phyper(q-1,m,n,k,lower.tail = F)
print(paste("Overlap P-value:",round(pvalue.overlap,digits=3),sep=" "))
[1] "Overlap P-value: 0.012"

3.8 Create individual tables for Data Set S2 (with information about undetectable genes)

#alternative function to convert gene names into corresponding loci
#this function uses E. coli genome annotation to extract locus tag
convert.gene.name.to.locus.tag<-function(geneNames)
{
  output<-c()
  #read E. coli genome information
  ecoli.genome<-read.csv("../Data/Miscellaneous_files/ecoli_gene_ids.csv",header=T)
  #define locus tag for each gene of the input set
  for(g in geneNames)
  {
    #first, evaluate if the current name is the standard gene symbol
    current.gene.position<-which(ecoli.genome$Symbol == g)
    #second, evaluate if the current name is a synonym 
    current.gene.alternative.position<-grep(g,ecoli.genome$Aliases)
    #for the fist case, extract locus id 
    if(length(current.gene.position)==1)
    {
      output<-c(output,strsplit(ecoli.genome$Aliases[current.gene.position],split = ",")[[1]][1])
    }
    #in the second scenario
    if(length(current.gene.position)==0) 
    {
      #extract the locus id
      if(length(current.gene.alternative.position)==1)
      {
        output<-c(output,strsplit(ecoli.genome$Aliases[current.gene.alternative.position],split = ",")[[1]][1])
      }
    #if the current name was not found or more than one potential loci were identified, keep the original gene name   
    if(length(current.gene.alternative.position)!=1)
    {
      output<-c(output,g)
    }
    }
  }
  output
}
#write CSV files with genes depleted along the TetR experiment
for(i in 1:7)
{
  #create table with name of depleted genes and the corresponding loci
  temporal.table<-cbind(tetR.depleted.genes[[i]],convert.gene.name.to.locus.tag(tetR.depleted.genes[[i]]))
  colnames(temporal.table)<-c("Gene Name","Locus")
  write.csv(file=paste("../../Supplement/Dataset S2/TetR_",names(tetR.depleted.genes)[i],"_depleted_genes.csv",sep=""),temporal.table,quote = F,row.names = F)
}
#write CSV file with information about overlap between time points
tetR.depleted.genes.comparison.table<-matrix(nrow=7,ncol=7,dimnames=list(names(tetR.depleted.genes),names(tetR.depleted.genes)),0)
for(r in 1:7)
{
  for(c in 1:7)
  {
    tetR.depleted.genes.comparison.table[r,c]<-length(intersect(tetR.depleted.genes[[r]],tetR.depleted.genes[[c]]))
  }
}
 write.csv(file="../../Supplement/Dataset S2/TetR_gene_depletion_comparison.csv",tetR.depleted.genes.comparison.table)
#write CSV files with genes depleted in the WT experiments
for(i in 1:7)
{
  temporal.table<-cbind(wt.depleted.genes[[i]],convert.gene.name.to.locus.tag(wt.depleted.genes[[i]]))
  colnames(temporal.table)<-c("Gene Name","Locus")
  write.csv(file=paste("../../Supplement/Dataset S2/WT_",names(wt.depleted.genes)[i],"_depleted_genes.csv",sep=""),temporal.table,quote = F,row.names = F)
}
#write CSV file with information about overlap between time points
wt.depleted.genes.comparison.table<-matrix(nrow=7,ncol=7,dimnames=list(names(wt.depleted.genes),names(wt.depleted.genes)),0)
for(r in 1:7)
{
  for(c in 1:7)
  {
    wt.depleted.genes.comparison.table[r,c]<-length(intersect(wt.depleted.genes[[r]],wt.depleted.genes[[c]]))
  }
}
 write.csv(file="../../Supplement/Dataset S2/WT_gene_depletion_comparison.csv",wt.depleted.genes.comparison.table)

3.9 Create single files for Data Set S1

#write CSV files with raw read counts for KO designs in WT and TetR KO libraries
temporal.table<-cbind(rownames(tetR.ko.read.counts.numeric),tetR.ko.library.count.matrix.with.gene.info[rownames(tetR.ko.read.counts.numeric),"gene"],tetR.ko.read.counts.numeric)
colnames(temporal.table)[1:6]<-c("Design ID","Gene","C0-a","C0-b","C0-c","C0-d")
write.csv(file="../../Supplement/Dataset S1/TetR_raw_read_counts.csv",temporal.table,quote = F,row.names = F)
#repeat for WT
temporal.table<-cbind(rownames(wt.ko.read.counts.numeric),wt.ko.library.count.matrix.with.gene.info[rownames(wt.ko.read.counts.numeric),"gene"],wt.ko.read.counts.numeric)
colnames(temporal.table)[1:6]<-c("Design ID","Gene","C0-a","C0-b","C0-c","C0-d")
write.csv(file="../../Supplement/Dataset S1/WT_raw_read_counts.csv",temporal.table,quote = F,row.names = F)
#save CSV files with ALDEx2 output
#tetR KO library
write.csv(file="../../Supplement/Dataset S1/TetR_t1+tet_vs_t0.csv",tetR.ko.iqlr.c0.c1.plus)
write.csv(file="../../Supplement/Dataset S1/TetR_t1-tet_vs_t0.csv",tetR.ko.iqlr.c0.c1.minus)
write.csv(file="../../Supplement/Dataset S1/TetR_t2+tet_vs_t0.csv",tetR.ko.iqlr.c0.c2.plus)
write.csv(file="../../Supplement/Dataset S1/TetR_t2-tet_vs_t0.csv",tetR.ko.iqlr.c0.c2.minus)
#wt KO library
write.csv(file="../../Supplement/Dataset S1/WT_t1+tet_vs_t0.csv",wt.ko.iqlr.c0.c1.plus)
write.csv(file="../../Supplement/Dataset S1/WT_t1-tet_vs_t0.csv",wt.ko.iqlr.c0.c1.minus)
write.csv(file="../../Supplement/Dataset S1/WT_t2+tet_vs_t0.csv",wt.ko.iqlr.c0.c2.plus)
write.csv(file="../../Supplement/Dataset S1/WT_t2-tet_vs_t0.csv",wt.ko.iqlr.c0.c2.minus)
#save CSV files with information of all genes affecting fitness in the TetR KO library
#this leverages previously constructed matrix that compiled effect of gene deletions
tetR.gene.KO.fitness.effect<-input.matrix.for.heatmap[which(input.matrix.for.heatmap[,"TetR"]!=0),"TetR"]
tetR.genes.impacting.fitness<-names(tetR.gene.KO.fitness.effect)
tetR.deletion.effect<-c()
tetR.specificity<-c()
for(r in 1:length(tetR.gene.KO.fitness.effect))
{
  if(tetR.gene.KO.fitness.effect[r]==1)
  {
  tetR.deletion.effect<-c(tetR.deletion.effect,"Positive")
  }
  if(tetR.gene.KO.fitness.effect[r]==-1)
  {
  tetR.deletion.effect<-c(tetR.deletion.effect,"Negative")
  }
  if(input.matrix.for.heatmap[tetR.genes.impacting.fitness[r],"WT"]==0)
  {
  tetR.specificity<-c(tetR.specificity,"Yes")
  }
  if(input.matrix.for.heatmap[tetR.genes.impacting.fitness[r],"WT"]!=0)
  {
  tetR.specificity<-c(tetR.specificity,"No")
  }
}
temporal.table<-cbind(tetR.genes.impacting.fitness,tetR.deletion.effect,tetR.specificity)
colnames(temporal.table)<-c("Gene","Deletion effect","TetR-specific?")
temporal.table<-temporal.table[order(temporal.table[,"Gene"]),]
write.csv(file="../../Supplement/Dataset S1/TetR_genes_impacting_fitness.csv",temporal.table,quote = F,row.names = F)
#create similar table for WT KO library
wt.gene.KO.fitness.effect<-input.matrix.for.heatmap[which(input.matrix.for.heatmap[,"WT"]!=0),"WT"]
wt.genes.impacting.fitness<-names(wt.gene.KO.fitness.effect)
wt.deletion.effect<-c()
wt.specificity<-c()
for(r in 1:length(wt.gene.KO.fitness.effect))
{
  if(wt.gene.KO.fitness.effect[r]==1)
  {
  wt.deletion.effect<-c(wt.deletion.effect,"Positive")
  }
  if(wt.gene.KO.fitness.effect[r]==-1)
  {
  wt.deletion.effect<-c(wt.deletion.effect,"Negative")
  }
  if(input.matrix.for.heatmap[wt.genes.impacting.fitness[r],"TetR"]==0)
  {
  wt.specificity<-c(wt.specificity,"Yes")
  }
  if(input.matrix.for.heatmap[wt.genes.impacting.fitness[r],"TetR"]!=0)
  {
  wt.specificity<-c(wt.specificity,"No")
  }
}
temporal.table<-cbind(wt.genes.impacting.fitness,wt.deletion.effect,wt.specificity)
colnames(temporal.table)<-c("Gene","Deletion effect","WT-specific?")
temporal.table<-temporal.table[order(temporal.table[,"Gene"]),]
write.csv(file="../../Supplement/Dataset S1/WT_genes_impacting_fitness.csv",temporal.table,quote = F,row.names = F)

4.1 Fig. 4A

#function to change format of time data so it can be read by Growthcurver
change.time.format<-function(time.vector)
{
  output<-c()
  for(x in time.vector)
  {
    #read time in the HH:MM:SS format and convert it to decimal format
    current.time.point<-strsplit(x,split = ":")[[1]]
    output<-c(output, as.numeric(current.time.point[1]) + ((as.numeric(current.time.point[3]) + (60*as.numeric(current.time.point[2])))/3600))
  }
  output<-round(output,digits = 3)
  output
}
#function to estimate the average and standard deviation (sd) of each strain (taking into account all of its replicates) at each time point
#the input data frame should have three columns: "Time","Strain" and "OD". The latter is the OD readings collected in the Bioscreen experiment
compute.mean.and.sd<-function(growth.df)
{
  output<-c()
  measured.time.points<-unique(growth.df$Time)
  #for each time point
  for(t in measured.time.points)
  {
    #for each strain
    for(s in unique(growth.df$Strain))
    {
     #compute mean OD reading value    
     average.current.strain.and.time.point<-mean(growth.df$OD[which(growth.df$Strain==s & growth.df$Time==t)])
     #compute corresponding SD
     sd.current.strain.and.time.point<-sd(growth.df$OD[which(growth.df$Strain==s & growth.df$Time==t)])
     output<-rbind(output,cbind(t,s,average.current.strain.and.time.point,sd.current.strain.and.time.point))
    }
  }
  #add column names
  colnames(output)<-c("Time","Strain","OD","sd")
  #make sure data frame format is good for downstream analyses
  output<-as.data.frame(output)
  output$Time<-as.numeric(as.vector(output$Time))
  output$OD<-as.numeric(as.vector(output$OD))
  output$sd<-as.numeric(as.vector(output$sd))
  output
}
#read OD readings from Bioscreen experiment to generate corresponding growth curves
#there were five strains in the experiment
#for each strain/tetracycline concentration, there are three biological replicates (each one with two replicates)
#bioscreen experiment was performed for a total of 48h
growth.data<-read.csv("../Data/Fitness_BioscreenC/20220504_formatted_data.csv",row.names=1)
#change time format
time.data<-change.time.format(rownames(growth.data))
#update row names with time in new format
rownames(growth.data)<-round(time.data,digits = 2)
#normalize data by subtracting minimum OD reading per well
growth.data.normalized<-c()
for(i in 1:ncol(growth.data))
{
  minimum.reading.current.well<-min(growth.data[,i])
  growth.data.normalized<-cbind(growth.data.normalized,
                                growth.data[,i]-minimum.reading.current.well)
}
#add column names
colnames(growth.data.normalized)<-colnames(growth.data)
#add row names
rownames(growth.data.normalized)<-rownames(growth.data)
#these are the tetracycline concentrations included in the experiment
tetracycline.concentrations<-seq(0,24,by=4) # ug/ml
#labels for the five strains in the dataset
strains<-c("WT","WTarcA","TetR","TetRarcA","pRB3arcA")
#color to be used for each strain
strain.colors<-c(WT="#66C2A5",WTarcA="#FC8D62",TetR="#8DA0CB",TetRarcA="#E78AC3",pRB3arcA="#A6D854")
#the OD data has been formatted such as the name of each well contains the information about the strain and the tetracycline concentration
#for example: TetR_20 means that the well was inoculated with the TetR strain and 20 ug/ml of tetracycline
#create Fig. 3A left panel (ie, antibiotic-free)
#create data frame
antibiotic.free.cultures.df<-c()
#loop to compile OD data for all five strains
for(s in strains)
{
  current.strain.concentration<-paste(s,0,sep="_")
  #identify the position of all replicates for the current strain/concentration combination
  replicates.positions<-grep(current.strain.concentration,colnames(growth.data.normalized))
  #add OD readings (first 24h) of the relevant replicates to the data frame
  for(r in replicates.positions)
  {
    antibiotic.free.cultures.df<-rbind(antibiotic.free.cultures.df,cbind(rownames(growth.data.normalized)[1:50],growth.data.normalized[1:50,r],rep(s,50)))
  }
}
#add column names
colnames(antibiotic.free.cultures.df)<-c("Time","OD","Strain")
#make sure data frame format is correct
antibiotic.free.cultures.df<-as.data.frame(antibiotic.free.cultures.df)
antibiotic.free.cultures.df$Strain <- as.factor(antibiotic.free.cultures.df$Strain)
antibiotic.free.cultures.df$Time<- as.numeric(as.vector(antibiotic.free.cultures.df$Time))
antibiotic.free.cultures.df$OD<- as.numeric(as.vector(antibiotic.free.cultures.df$OD))
#compute mean and sd per strain/concentration/time point combination
antibiotic.free.cultures.df.v2 <- compute.mean.and.sd(antibiotic.free.cultures.df)
#create ggplot object to generate final figure
antibiotic.free.subpanel<- ggplot(antibiotic.free.cultures.df.v2, aes(x=Time,y=OD, group=Strain,colour=Strain)) + 
  geom_line() +
  geom_point()+
  geom_errorbar(aes(ymin=OD-sd, ymax=OD+sd), width=0.75,alpha=0.75)+
  theme_classic()
#create Fig. 4A right panel
#treatment with 20 ug/ml of tetracycline
tet.concentration<- 20
#create data frame to store OD readings 
#only TetR, TetR DarcA and TetR DarcA + pRB3-arcA (episomal complemented strain) were treated with tetracycline
tetracycline.treated.cultures.df<-c()
  for(s in strains[3:5])
  {
    current.strain.concentration<-paste(s,tet.concentration,sep="_")
    #identify the position of all replicates for the current strain/concentration combination
    replicates.positions<-grep(current.strain.concentration,colnames(growth.data))
    #add OD readings (full 48h) for the relevant replicates to the data frame
    for(r in replicates.positions)
    {
      tetracycline.treated.cultures.df<-rbind(tetracycline.treated.cultures.df,cbind(rownames(growth.data.normalized),growth.data.normalized[,r],rep(s,nrow(growth.data.normalized))))
    }
  }
  #add column names  
  colnames(tetracycline.treated.cultures.df)<-c("Time","OD","Strain")
  #make sure data frame format is correct
  tetracycline.treated.cultures.df<-as.data.frame(tetracycline.treated.cultures.df)
  tetracycline.treated.cultures.df$Strain <- as.factor(tetracycline.treated.cultures.df$Strain)
  tetracycline.treated.cultures.df$Time<- as.numeric(as.vector(tetracycline.treated.cultures.df$Time))
  tetracycline.treated.cultures.df$OD<- as.numeric(as.vector(tetracycline.treated.cultures.df$OD))
  #compute mean and sd per strain/concentration/time point combination
  tetracycline.treated.cultures.df.v2 <- compute.mean.and.sd(tetracycline.treated.cultures.df)
  #create ggplot object to generate final figure
  tetracycline.treated.subpanel<- ggplot(tetracycline.treated.cultures.df.v2, aes(x=Time,y=OD, group=Strain,colour=Strain)) + 
    geom_line() +
    geom_point()+
    geom_errorbar(aes(ymin=OD-sd, ymax=OD+sd), width=0.75,alpha=0.15)+
    theme_classic()
  #generate Fig. 4A
grid.arrange(antibiotic.free.subpanel + scale_color_manual(values=strain.colors)+ 
theme(axis.text=element_text(size=10),axis.title = element_text(size=10,face="bold")) + xlab("Time (h)") + ylab("OD600")+ggtitle("[TET]=0"),tetracycline.treated.subpanel+ scale_color_manual(values=strain.colors[3:5])+ 
theme(axis.text=element_text(size=10),axis.title = element_text(size=10,face="bold")) + xlab("Time (h)") + ylab("OD600")+ggtitle("[TET]=20ug/ml"),nrow=1)

4.2 Fig. S3

#plot growth curves of WT and TetR in antibiotic-free cultures 
#create ggplot object
temporal.plot<- ggplot(antibiotic.free.cultures.df.v2[which(antibiotic.free.cultures.df.v2$Strain =="WT" | antibiotic.free.cultures.df.v2$Strain == "TetR"),]
                       , aes(x=Time,y=OD, group=Strain,colour=Strain)) + 
  geom_line() +
  geom_point()+
  geom_errorbar(aes(ymin=OD-sd, ymax=OD+sd), width=0.75,alpha=0.5)+
  theme_classic()
print(temporal.plot + scale_color_manual(values=strain.colors[c(1,3)])+ 
        theme(axis.text=element_text(size=10),axis.title = element_text(size=10,face="bold")) + xlab("Time (h)")+ylab("OD600")+ggtitle("Fig. S3"))

#estimate fitness parameters shown in Fig. S3 with Growthcurver (for the first 24h of growth)
time.vector<-as.vector(time.data)
input.matrix.growthcurver<-as.data.frame(cbind(time.data[1:50],growth.data.normalized[1:50,]))
#rename column with time values
colnames(input.matrix.growthcurver)[1]<-"time"
#run Growthcurver
growthcurver.output <- SummarizeGrowthByPlate(input.matrix.growthcurver)
#print estimated max growth rate (mu) for WT and TetR in antibiotic-free medium
print(paste("mu (WT in LB without tetracycline) was:",round(mean(growthcurver.output[grep("WT_0",growthcurver.output$sample),"r"]),digits=2),sep=""))
[1] "mu (WT in LB without tetracycline) was:1.15"
print(paste("mu (TetR in LB without tetracycline) was:",round(mean(growthcurver.output[grep("TetR_0",growthcurver.output$sample),"r"]),digits=2),sep=""))
[1] "mu (TetR in LB without tetracycline) was:0.8"
#print estimated area under the growth curve (AUC) values for WT and TetR in antibiotic-free medium
print(paste("AUC (WT in LB without tetracycline) was:",round(mean(growthcurver.output[grep("WT_0",growthcurver.output$sample),"auc_e"]),digits=2),sep=""))
[1] "AUC (WT in LB without tetracycline) was:30.29"
print(paste("AUC (TetR in LB without tetracycline) was:",round(mean(growthcurver.output[grep("TetR_0",growthcurver.output$sample),"auc_e"]),digits=2),sep=""))
[1] "AUC (TetR in LB without tetracycline) was:20.44"

4.3 Fig. 4B-C

#read OD data collected in experiment to evaluate the effect of arcA deletion in WT and TetR over three growth cycles
#in each cycle, cultures were started at an OD600 of 0.1 and grown to an OD600 of 1.0
#and thereafter diluted in fresh medium to OD600 of 0.1 to start a new cycle of growth
#three replicates per strain/antibiotic concentration were included
#last two columns are LB controls 
cyclic.growth.od<-read.csv("../Data/cyclic_growth/macrodilution_cyclic_growth_experiment_OD_data.csv",header=T)
#change format of time as before
cyclic.growth.od$Time<-change.time.format(cyclic.growth.od$Time)
par(mfrow=c(1,3))
#plot individual growth curves of TetR replicates in tetracycline-free LB
#replicate A
plot(x=cyclic.growth.od$Time[which(cyclic.growth.od$TetR_0_A!="")],y=cyclic.growth.od$TetR_0_A[which(cyclic.growth.od$TetR_0_A!="")],col=strain.colors["TetR"],pch=0,type="o",xlab="Time (h)",ylab="OD600",xlim=c(0,10),ylim=c(0,1.1),cex.axis=1.5,cex.lab=1.5,main="[TET]=0")  
#replicate B
points(x=cyclic.growth.od$Time[which(cyclic.growth.od$TetR_0_B!="")],y=cyclic.growth.od$TetR_0_B[which(cyclic.growth.od$TetR_0_B!="")],col=strain.colors["TetR"],pch=1,type="o")  
#replicate C
points(x=cyclic.growth.od$Time[which(cyclic.growth.od$TetR_0_C!="")],y=cyclic.growth.od$TetR_0_C[which(cyclic.growth.od$TetR_0_C!="")],col=strain.colors["TetR"],pch=2,type="o")  
#plot individual growth curves of TetR DarcA replicates in tetracycline-free LB
#replicate A
points(x=cyclic.growth.od$Time[which(cyclic.growth.od$TetRarcA_0_A!="")],y=cyclic.growth.od$TetRarcA_0_A[which(cyclic.growth.od$TetRarcA_0_A!="")],col=strain.colors["TetRarcA"],pch=0,type="o")  
#replicate B
points(x=cyclic.growth.od$Time[which(cyclic.growth.od$TetRarcA_0_B!="")],y=cyclic.growth.od$TetRarcA_0_B[which(cyclic.growth.od$TetRarcA_0_B!="")],col=strain.colors["TetRarcA"],pch=1,type="o")  
#replicate C
points(x=cyclic.growth.od$Time[which(cyclic.growth.od$TetRarcA_0_C!="")],y=cyclic.growth.od$TetRarcA_0_C[which(cyclic.growth.od$TetRarcA_0_C!="")],col=strain.colors["TetRarcA"],pch=2,type="o")  
abline(h=1,col="darkgrey",lty=2)
#plot individual growth curves of TetR replicates in LB with 20 ug/ml of tetracycline
#replicate A
plot(x=cyclic.growth.od$Time[which(cyclic.growth.od$TetR_20_A!="")],y=cyclic.growth.od$TetR_20_A[which(cyclic.growth.od$TetR_20_A!="")],col=strain.colors["TetR"],pch=0,type="o",xlab="Time (h)",ylab="OD600",xlim=c(0,40),ylim=c(0,1.1),cex.axis=1.5,cex.lab=1.5,main="[TET]=20 ug/ml")  
#replicate B
points(x=cyclic.growth.od$Time[which(cyclic.growth.od$TetR_20_B!="")],y=cyclic.growth.od$TetR_20_B[which(cyclic.growth.od$TetR_20_B!="")],col=strain.colors["TetR"],pch=1,type="o")  
#replicate C
points(x=cyclic.growth.od$Time[which(cyclic.growth.od$TetR_20_C!="")],y=cyclic.growth.od$TetR_20_C[which(cyclic.growth.od$TetR_20_C!="")],col=strain.colors["TetR"],pch=2,type="o")  
#plot individual growth curves of TetR DarcA replicates in LB with 20 ug/ml
#replicate A
points(x=cyclic.growth.od$Time[which(cyclic.growth.od$TetRarcA_20_A!="")],y=cyclic.growth.od$TetRarcA_20_A[which(cyclic.growth.od$TetRarcA_20_A!="")],col=strain.colors["TetRarcA"],pch=0,type="o")  
#replicate B
points(x=cyclic.growth.od$Time[which(cyclic.growth.od$TetRarcA_20_B!="")],y=cyclic.growth.od$TetRarcA_20_B[which(cyclic.growth.od$TetRarcA_20_B!="")],col=strain.colors["TetRarcA"],pch=1,type="o")  
#replicate C
points(x=cyclic.growth.od$Time[which(cyclic.growth.od$TetRarcA_20_C!="")],y=cyclic.growth.od$TetRarcA_20_C[which(cyclic.growth.od$TetRarcA_20_C!="")],col=strain.colors["TetRarcA"],pch=2,type="o")  
abline(h=1,col="darkgrey",lty=2)
#add legend
plot.new()
legend("center",col=strain.colors[c("TetR","TetRarcA")],legend = c("TetR",expression(paste("TetR ",Delta, "arcA"))),lty=1)

4.4 Fig. S6

#create same plot for WT and WT DarcA
par(mfrow=c(1,3))
#plot individual growth curves of WT replicates in tetracycline-free LB
#replicate A
plot(x=cyclic.growth.od$Time[which(cyclic.growth.od$WT_0_A!="")],y=cyclic.growth.od$WT_0_A[which(cyclic.growth.od$WT_0_A!="")],col=strain.colors["WT"],pch=0,type="o",xlab="Time (h)",ylab="OD600",xlim=c(0,7),ylim=c(0,1.1),cex.axis=1.5,cex.lab=1.5,main="[TET]=0") #replicate B
points(x=cyclic.growth.od$Time[which(cyclic.growth.od$WT_0_B!="")],y=cyclic.growth.od$WT_0_B[which(cyclic.growth.od$WT_0_B!="")],col=strain.colors["WT"],pch=1,type="o")  
#replicate C
points(x=cyclic.growth.od$Time[which(cyclic.growth.od$WT_0_C!="")],y=cyclic.growth.od$WT_0_C[which(cyclic.growth.od$WT_0_C!="")],col=strain.colors["WT"],pch=2,type="o")  
#plot individual growth curves of WT DarcA replicates in tetracycline-free LB
#replicate A
points(x=cyclic.growth.od$Time[which(cyclic.growth.od$WTarcA_0_A!="")],y=cyclic.growth.od$WTarcA_0_A[which(cyclic.growth.od$WTarcA_0_A!="")],col=strain.colors["WTarcA"],pch=0,type="o")  
#replicate B
points(x=cyclic.growth.od$Time[which(cyclic.growth.od$WTarcA_0_B!="")],y=cyclic.growth.od$WTarcA_0_B[which(cyclic.growth.od$WTarcA_0_B!="")],col=strain.colors["WTarcA"],pch=1,type="o")  
#replicate C
points(x=cyclic.growth.od$Time[which(cyclic.growth.od$WTarcA_0_C!="")],y=cyclic.growth.od$WTarcA_0_C[which(cyclic.growth.od$WTarcA_0_C!="")],col=strain.colors["WTarcA"],pch=2,type="o")  
abline(h=1,col="darkgrey",lty=2)
#plot individual growth curves of WT replicates in LB with 0.75 ug/ml of tetracycline
#replicate A
plot(x=cyclic.growth.od$Time[which(cyclic.growth.od$WT_0.75_A!="")],y=cyclic.growth.od$WT_0.75_A[which(cyclic.growth.od$WT_0.75_A!="")],col=strain.colors["WT"],pch=0,type="o",xlab="Time (h)",ylab="OD600",xlim=c(0,30),ylim=c(0,1.1),cex.axis=1.5,cex.lab=1.5,main="[TET]=0.75 ug/ml")  
#replicate B
points(x=cyclic.growth.od$Time[which(cyclic.growth.od$WT_0.75_B!="")],y=cyclic.growth.od$WT_0.75_B[which(cyclic.growth.od$WT_0.75_B!="")],col=strain.colors["WT"],pch=1,type="o")  
#replicate C
points(x=cyclic.growth.od$Time[which(cyclic.growth.od$WT_0.75_C!="")],y=cyclic.growth.od$WT_0.75_C[which(cyclic.growth.od$WT_0.75_C!="")],col=strain.colors["WT"],pch=2,type="o")  
#plot individual growth curves of WT DarcA replicates in LB with 0.75 ug/ml
#replicate A
points(x=cyclic.growth.od$Time[which(cyclic.growth.od$WTarcA_0.75_A!="")],y=cyclic.growth.od$WTarcA_0.75_A[which(cyclic.growth.od$WTarcA_0.75_A!="")],col=strain.colors["WTarcA"],pch=0,type="o")  
#replicate B
points(x=cyclic.growth.od$Time[which(cyclic.growth.od$WTarcA_0.75_B!="")],y=cyclic.growth.od$WTarcA_0.75_B[which(cyclic.growth.od$WTarcA_0.75_B!="")],col=strain.colors["WTarcA"],pch=1,type="o")  
#replicate C
points(x=cyclic.growth.od$Time[which(cyclic.growth.od$WTarcA_0.75_C!="")],y=cyclic.growth.od$WTarcA_0.75_C[which(cyclic.growth.od$WTarcA_0.75_C!="")],col=strain.colors["WTarcA"],pch=2,type="o")  
abline(h=1,col="darkgrey",lty=2)
#add legend
plot.new()
legend("center",col=strain.colors[c("WT","WTarcA")],legend = c("WT",expression(paste("WT ",Delta, "arcA"))),lty=1)

4.5 Fig. 4D

#run Growthcurver analysis again
input.matrix.growthcurver<-as.data.frame(cbind(time.data,growth.data.normalized))
#rename column with time information
colnames(input.matrix.growthcurver)[1]<-"time"
#run Growthcurver for the full 48h
growthcurver.output <- SummarizeGrowthByPlate(input.matrix.growthcurver)
#create Fig. 4D (left panel)
#data frame with Growthcurver-estimated AUCs of TetR, TetR DarcA and TetR DarcA + pRB3-arcA (episomal complemented strain)
auc.df<-c()
#extract AUC values of TetR from Growthcurver output
tetR.samples.positions<-grep("TetR_",growthcurver.output[,"sample"])
tetR.auc<-growthcurver.output[tetR.samples.positions,"auc_e"]
names(tetR.auc)<-growthcurver.output[tetR.samples.positions,"sample"]
#compute mean and SD for AUC values for each tetracycline concentration
temporal.auc.matrix<-cbind(sapply(1:7,function(x){mean(tetR.auc[((x-1)*6)+1:6])}),
                          sapply(1:7,function(x){sd(tetR.auc[((x-1)*6)+1:6])}))
#add values to data frame 
auc.df<-rbind(auc.df,temporal.auc.matrix)
#extract AUC values of TetR DarcA from Growthcurver output
tetR.arcA.samples.positions<-grep("TetRarcA_",growthcurver.output[,"sample"])
tetR.arcA.auc<-growthcurver.output[tetR.arcA.samples.positions,"auc_e"]
names(tetR.arcA.auc)<-growthcurver.output[tetR.arcA.samples.positions,"sample"]
#compute mean and SD for AUC values for each tetracycline concentration
temporal.auc.matrix<-cbind(sapply(1:7,function(x){mean(tetR.arcA.auc[((x-1)*6)+1:6])}),
                   sapply(1:7,function(x){sd(tetR.arcA.auc[((x-1)*6)+1:6])}))
#add values to data frame 
auc.df<-rbind(auc.df,temporal.auc.matrix)
#extract AUC values of TetR DarcA + pRB3-arcA from Growthcurver output
tetR.arcA.pRB3.samples.positions<-grep("pRB3arcA_",growthcurver.output[,"sample"])
tetR.arcA.pRB3.auc<-growthcurver.output[tetR.arcA.pRB3.samples.positions,"auc_e"]
names(tetR.arcA.pRB3.auc)<-growthcurver.output[tetR.arcA.pRB3.samples.positions,"sample"]
#compute mean and SD for AUC values for each tetracycline concentration
temporal.auc.matrix<-cbind(sapply(1:7,function(x){mean(tetR.arcA.pRB3.auc[((x-1)*6)+1:6])}),
                   sapply(1:7,function(x){sd(tetR.arcA.pRB3.auc[((x-1)*6)+1:6])}))
#add values to data frame 
auc.df<-rbind(auc.df,temporal.auc.matrix)
#make sure data frame format is correct
auc.tet.concentrations<-factor(rep(tetracycline.concentrations,3),levels = seq(0,24,by=4))
auc.strains<-factor(rep(c("TetR","TetRarcA","pRB3arcA"),each=7),levels = c("TetR","TetRarcA","pRB3arcA"))
#add columns with tetracycline concentration and strain information
auc.df<-cbind(as.data.frame(auc.df),auc.tet.concentrations,auc.strains)
colnames(auc.df)<-c("auc","sd","Concentration","Strain")
#create ggplot object
plot.auc.estimates<- ggplot(auc.df, aes(x=Concentration,y=auc, group=Strain,colour=Strain)) +
  geom_line() +
  geom_point()+
  geom_errorbar(aes(ymin=auc-sd, ymax=auc+sd), width=0.75) + theme_classic() +theme(aspect.ratio = 1)
#similar analysis for lag phase proxy (Fig. 4D right panel)
#point of inflection (ie, time point for 1/2 max OD) was used as a proxy for lag phase
#data frame with Growthcurver-estimated lag phase proxy of TetR, TetR DarcA and TetR DarcA + pRB3-arcA (episomal complemented strain)
lag.df<-c()
#extract point of inflection values of TetR from Growthcurver output
tetR.lag<-growthcurver.output[tetR.samples.positions,"t_mid"]
names(tetR.lag)<-growthcurver.output[tetR.samples.positions,"sample"]
#compute mean and SD for inflection point values for each tetracycline concentration
temporal.lag.matrix<-cbind(sapply(1:7,function(x){mean(tetR.lag[((x-1)*6)+1:6])}),
                   sapply(1:7,function(x){sd(tetR.lag[((x-1)*6)+1:6])}))
#add values to data frame 
lag.df<-rbind(lag.df,temporal.lag.matrix)
#extract point of inflection values of TetR DarcA from Growthcurver output
tetR.arcA.lag<-growthcurver.output[tetR.arcA.samples.positions,"t_mid"]
names(tetR.arcA.lag)<-growthcurver.output[tetR.arcA.samples.positions,"sample"]
#compute mean and SD for inflection point values for each tetracycline concentration
temporal.lag.matrix<-cbind(sapply(1:7,function(x){mean(tetR.arcA.lag[((x-1)*6)+1:6])}),
                   sapply(1:7,function(x){sd(tetR.arcA.lag[((x-1)*6)+1:6])}))
#add values to data frame 
lag.df<-rbind(lag.df,temporal.lag.matrix)
#extract point of inflection values of TetR DarcA + pRB3-arcA from Growthcurver output
tetR.arcA.pRB3.lag<-growthcurver.output[tetR.arcA.pRB3.samples.positions,"t_mid"]
temporal.lag.matrix<-cbind(sapply(1:7,function(x){mean(tetR.arcA.pRB3.lag[((x-1)*6)+1:6])}),
                   sapply(1:7,function(x){sd(tetR.arcA.pRB3.lag[((x-1)*6)+1:6])}))
#add values to data frame 
lag.df<-rbind(lag.df,temporal.lag.matrix)
#add columns with tetracycline concentration and strain information
lag.df<-cbind(as.data.frame(lag.df),auc.tet.concentrations,auc.strains)
colnames(lag.df)<-c("lag","sd","Concentration","Strain")
#if estimated point of inflection was > 48h, then the value was set to 48
lag.df$sd[which(lag.df$lag>48)]<-0
lag.df$lag[which(lag.df$lag>48)]<-48
#create ggplot object
plot.lag.estimates<- ggplot(lag.df, aes(x=Concentration,y=lag, group=Strain,colour=Strain)) +
  geom_line() +
  geom_point()+
  geom_errorbar(aes(ymin=lag-sd, ymax=lag+sd), width=0.75) + theme_classic() +theme(aspect.ratio = 1)
#create Fig. 4D
grid.arrange(plot.auc.estimates + scale_color_manual(values=strain.colors[3:5])+
        theme(axis.text=element_text(size=10), axis.title = element_text(size=10),
              panel.border = element_rect(colour = "black", fill=NA, size=0.5)) 
      + xlab("[TET](ug/ml)")+ylab("AUC")+ggtitle("Fig. 4D"), plot.lag.estimates + scale_color_manual(values=strain.colors[3:5])+
        theme(axis.text=element_text(size=10), axis.title = element_text(size=10),
              panel.border = element_rect(colour = "black", fill=NA, size=0.5))
      + xlab("[TET](ug/ml)")+ylab("~Lag phase (h)"), nrow=1)

4.6 Fig. 4E

#raw and processed data is available in the "Data/NADH_NAD/nadh_nad_measurement.xlsx" file
#results are the compilation of two independent experiments
#in each experiment, the NADH and NAD concentrations of WT, WT DarcA, TetR and TetR DarcA were measured with and without tetracycline (0.75 ug/ml for WT and WT DarcA, and 4 ug/ml for TetR and TetR DarcA)
#NADH/NAD ratios in 1st experiment, cultures without tetracycline
wt.no.tetracycline.expt1<-c(0.025735294,0.052434457,0.046875)
wt.arcA.no.tetracycline.expt1<-c(0.071917808,0.081632653,0.070110701)
tetR.no.tetracycline.expt1<-c(0.075117371,0.081545064,0.043715847)
tetR.arcA.no.tetracycline.expt1<-c(0.380645161,0.129943503,0.197740113)
#NADH/NAD ratios in 1st experiment, cultures with tetracycline
wt.with.tetracycline.expt1<-c(0.05524861878,0.02032520325,0.02926829268)
wt.arcA.with.tetracycline.expt1<-c(0.04545454545,0.0351758794,0.05803571429)
tetR.with.tetracycline.expt1<-c(0.1631944444,0.1936507937,0.1032258065)
tetR.arcA.with.tetracycline.expt1<-c(0.1302931596,0.3312883436,0.2218181818)
#NADH/NAD ratios in 2nd experiment, cultures without tetracycline
wt.no.tetracycline.expt2<-c(0.052816901,0.069204152)
wt.arcA.no.tetracycline.expt2<-c()
tetR.no.tetracycline.expt2<-c(0.06185567,0.052631579)
tetR.arcA.no.tetracycline.expt2<-c(0.090425532,0.142857143,0.11409396)
#NADH/NAD ratios in 2nd experiment, cultures with tetracycline
wt.with.tetracycline.expt2<-c(0.074074074,0.050458716)
wt.arcA.with.tetracycline.expt2<-c(0.045801527,0.036363636)
tetR.with.tetracycline.expt2<-c(0.116935484,0.120622568)
tetR.arcA.with.tetracycline.expt2<-c(0.092050209,0.055793991,0.089622642)
#combine data from the two experiments
#cultures without tetracycline
wt.no.tetracycline<-c(wt.no.tetracycline.expt1,wt.no.tetracycline.expt2)
wt.arcA.no.tetracycline<-c(wt.arcA.no.tetracycline.expt1,wt.arcA.no.tetracycline.expt2)
tetR.no.tetracycline<-c(tetR.no.tetracycline.expt1,tetR.no.tetracycline.expt2)
tetR.arcA.no.tetracycline<-c(tetR.arcA.no.tetracycline.expt1,tetR.arcA.no.tetracycline.expt2)
#cultures with tetracycline
wt.with.tetracycline<-c(wt.with.tetracycline.expt1,wt.with.tetracycline.expt2)
wt.arcA.with.tetracycline<-c(wt.arcA.with.tetracycline.expt1,wt.arcA.with.tetracycline.expt2)
tetR.with.tetracycline<-c(tetR.with.tetracycline.expt1,tetR.with.tetracycline.expt2)
tetR.arcA.with.tetracycline<-c(tetR.arcA.with.tetracycline.expt1,tetR.arcA.with.tetracycline.expt2)
boxplot(wt.no.tetracycline,wt.with.tetracycline,wt.arcA.no.tetracycline,wt.arcA.with.tetracycline,
        tetR.no.tetracycline,tetR.with.tetracycline,tetR.arcA.no.tetracycline,tetR.arcA.with.tetracycline, col=rep(strain.colors[1:4],each=2),
        names=paste(rep(c("WT","WT arcA","TetR","TetR arcA"),each=2),rep(c("(-)","(+)"),4),sep=""),las=2,
        ylab="NADH/NAD",ylim=c(0,0.4),cex=.7,cex.lab=.7, cex.axis=.7,main="Fig. 4E")

#T-test with respect to wt(-TET)
print(paste("T-test p-value for WT(-) vs WT arcA(-):",t.test(wt.no.tetracycline,wt.arcA.no.tetracycline)$p.value,sep=""))
[1] "T-test p-value for WT(-) vs WT arcA(-):0.0205071363870608"
print(paste("T-test p-value for WT(-) vs TetR(-):",t.test(wt.no.tetracycline,tetR.no.tetracycline)$p.value,sep=""))
[1] "T-test p-value for WT(-) vs TetR(-):0.207019700535709"
print(paste("T-test p-value for WT(-) vs TetR arcA(-):",t.test(wt.no.tetracycline,tetR.arcA.no.tetracycline)$p.value,sep=""))
[1] "T-test p-value for WT(-) vs TetR arcA(-):0.0329038018590071"
#T-test (-TET) vs (+TET) for each strain
print(paste("T-test p-value for WT(+) vs WT(-):",t.test(wt.no.tetracycline,wt.with.tetracycline)$p.value,sep=""))
[1] "T-test p-value for WT(+) vs WT(-):0.773695383582882"
print(paste("T-test p-value for WT arcA(+) vs WT arcA(-):",t.test(wt.arcA.no.tetracycline,wt.arcA.with.tetracycline)$p.value,sep=""))
[1] "T-test p-value for WT arcA(+) vs WT arcA(-):0.00162431938950198"
print(paste("T-test p-value for TetR(+) vs TetR(-):",t.test(tetR.no.tetracycline,tetR.with.tetracycline)$p.value,sep=""))
[1] "T-test p-value for TetR(+) vs TetR(-):0.00738632682251771"
print(paste("T-test p-value for TetR arcA(+) vs TetR arcA(-):",t.test(tetR.arcA.no.tetracycline,tetR.arcA.with.tetracycline)$p.value,sep=""))
[1] "T-test p-value for TetR arcA(+) vs TetR arcA(-):0.719428422469656"

5.1 Fig. 5A

#read metabolome similarity matrix from Campos & Zampieri 2019 (Molecular cell-Table S3)
similarity.matrix<-read.csv("../Data/Metabolic_profiles/Campos_Zampieri_data/drug_gene_similarity_matrix.csv",row.names=1)
#read matrix with p-values for metabolic profile similarity from Campos & Zampieri 2019 (Molecular cell-Table S3)
pvalue.matrix<-read.csv("../Data/Metabolic_profiles/Campos_Zampieri_data/drug_gene_similarity_pvalue.csv",row.names=1)
#generate Fig. 5A
plot(x=similarity.matrix[,"arcA"],y=-1*log10(pvalue.matrix[rownames(similarity.matrix),"arcA"]),xlab="Drug treatment-arcA KO similarity",ylab="-log10 p-value", main="Fig. 5A")
#highlight the two treatments more similar to the arcA deletion
points(x=similarity.matrix[grep("Cefpiramide",rownames(similarity.matrix)),"arcA"],y=-1*log10(pvalue.matrix[grep("Cefpiramide",rownames(pvalue.matrix)),"arcA"]),col="red",pch=19)
text(x=similarity.matrix[grep("Cefpiramide",rownames(similarity.matrix)),"arcA"]-0.02,y=-1*log10(pvalue.matrix[grep("Cefpiramide",rownames(pvalue.matrix)),"arcA"]),"Cefpiramide")
points(x=similarity.matrix[grep("Sertraline",rownames(similarity.matrix)),"arcA"],y=-1*log10(pvalue.matrix[grep("Sertraline",rownames(pvalue.matrix)),"arcA"]),col="darkblue",pch=19)
text(x=similarity.matrix[grep("Sertraline",rownames(similarity.matrix)),"arcA"],y=-1*log10(pvalue.matrix[grep("Sertraline",rownames(pvalue.matrix)),"arcA"])+0.3,"Sertraline")

#check position of arcA KO metabolic profile within ranking  of all gene deletions for the top 2 compounds
arcA.sertraline.ranking<-length(which(as.numeric(similarity.matrix["Sertraline",]) > similarity.matrix["Sertraline","arcA"]))
print(paste("Position of arcA deletion in similarity ranking with respect to Sertraline treatment profile was:",arcA.sertraline.ranking+1,"/",nrow(similarity.matrix),sep=""))
[1] "Position of arcA deletion in similarity ranking with respect to Sertraline treatment profile was:17/1279"
arcA.cefpiramide.ranking<-length(which(as.numeric(similarity.matrix["Cefpiramide",]) > similarity.matrix["Cefpiramide","arcA"]))
print(paste("Position of arcA deletion in similarity ranking with respect to Cefpiramide treatment profile was:",arcA.cefpiramide.ranking+1,"/",nrow(similarity.matrix),sep=""))
[1] "Position of arcA deletion in similarity ranking with respect to Cefpiramide treatment profile was:19/1279"

5.2 Fig. S7

#read metabolic profiles of treated E. coli (z-scores) 
#the dataset contains E. coli metabolic profiles (969 metabolites) during treatment with 1,279 compounds
#data sourced from Campos & Zampieri 2019 (Molecular cell-Table S1)
zampieri.metabolic.profiles<-read.csv("../Data/Metabolic_profiles/Campos_Zampieri_data/zscores_metabolic_profile.csv",header=T)
#plot distribution of Z-scores in sertraline treatment
par(mfrow=c(1,2))
hist(zampieri.metabolic.profiles[,"Sertraline"],breaks=100,xlab="Metabolite z-score",main="Sertraline treatment")
#define threshold to consider a metabolite as responsive to sertraline (top 10% absolute value)
sertraline.zscore.threshold<-as.numeric(quantile(abs(zampieri.metabolic.profiles[,"Sertraline"]),0.9,na.rm = T))
#define metabolites whose concentration was altered by sertraline
sertraline.treatment.differential.metabolites<-zampieri.metabolic.profiles[which(abs(zampieri.metabolic.profiles[,"Sertraline"])>= sertraline.zscore.threshold),"Metabolite_ids"]
#remove duplication
sertraline.treatment.differential.metabolites<-unique(sertraline.treatment.differential.metabolites)
#remove empty entry
sertraline.treatment.differential.metabolites<-as.vector(sertraline.treatment.differential.metabolites[-26])
#split entries with multiple KEGG IDs
sertraline.treatment.differential.metabolites<-sapply(1:length(sertraline.treatment.differential.metabolites),function(x){strsplit(sertraline.treatment.differential.metabolites[x],split="~")[[1]]})
#save file with KEGG id of altered metabolites
#write.csv(file="../Data/Metabolic_profiles/Campos_Zampieri_data/differential_metabolites_sertraline_08302022.csv",array(as.character(unlist(sertraline.treatment.differential.metabolites))))
#repeat analysis for cefpiramide data
#plot distribution of Z-scores in cefpiramide treatment
hist(zampieri.metabolic.profiles[,"Cefpiramide"],breaks=100,xlab="Metabolite z-score",main="Cefpiramide treatment")

#define threshold to consider a metabolite as responsive to cefpiramide
cefpiramide.zscore.threshold<-as.numeric(quantile(abs(zampieri.metabolic.profiles[,"Cefpiramide"]),0.9,na.rm = T))
#define metabolites whose concentration was altered by cefpiramide
cefpiramide.treatment.differential.metabolites<-zampieri.metabolic.profiles[which(abs(zampieri.metabolic.profiles[,"Cefpiramide"])>= cefpiramide.zscore.threshold),"Metabolite_ids"]
#remove duplication
cefpiramide.treatment.differential.metabolites<-unique(cefpiramide.treatment.differential.metabolites)
#remove empty entry
cefpiramide.treatment.differential.metabolites<-as.vector(cefpiramide.treatment.differential.metabolites[-47])
#split entries with multiple KEGG IDs
cefpiramide.treatment.differential.metabolites<-sapply(1:length(cefpiramide.treatment.differential.metabolites),function(x){strsplit(cefpiramide.treatment.differential.metabolites[x],split="~")[[1]]})
#save IDs of altered metabolites
#write.csv(file="../Data/Metabolic_profiles/Campos_Zampieri_data/differential_metabolites_cefpiramide_related_08302022.csv",array(as.character(unlist(cefpiramide.treatment.differential.metabolites))))
#perform differential expression analysis of arcA KO transcriptional data from Park et al. 2013 (PLoS Genetics)
#read normalized GEO data (accession ID: GSE46415)
arcA.ko.park.transcriptomes<-read.csv("../Data/Differential_expression_analysis/GEO_Park2013/arcA_ko_transcriptomics_Park et al_2013.csv",header=T,row.names = 1)
#update row names with locus tag
rownames(arcA.ko.park.transcriptomes)<-sapply(1:nrow(arcA.ko.park.transcriptomes),function(x){strsplit(rownames(arcA.ko.park.transcriptomes)[x],split = "0710")[[1]][1]})
#log2 transform the values
arcA.ko.park.transcriptomes<-log2(arcA.ko.park.transcriptomes)
#perform differential expression analysis with BayesT as before
arcA.ko.response.park<-bayesT(arcA.ko.park.transcriptomes,numC = 3,numE = 3,conf = 7,doMulttest = T)
arcA.ko.degs.park<-rownames(arcA.ko.response.park)[which(arcA.ko.response.park$BH < 0.05 & abs(arcA.ko.response.park$meanC - arcA.ko.response.park$meanE)>1)]
#save file with DEGs
#write.csv(file="../Data/Metabolic_profiles/Campos_Zampieri_data/arcA_KO_DEGs_Park2013.csv",arcA.ko.degs.park)
#identify metabolites whose concentration is altered by the deletion of arcA
#data  sourced from Fuhrer et al. (Molecular Systems Biology 2017)
#data was downloaded from the BioStudies database (accession S-BSST5)
negative.ions.to.metabolites.map<-read.csv("../Data/Metabolic_profiles/Fuhrer_Zampieri_et_al_data/neg_kegg_all_3mD.csv")
positive.ions.to.metabolites.map<-read.csv("../Data/Metabolic_profiles/Fuhrer_Zampieri_et_al_data/pos_kegg_all_3mD.csv")
negative.ions.zscores<-read.csv("../Data/Metabolic_profiles/Fuhrer_Zampieri_et_al_data/negative_ions_zscores_gene_kos.csv",header=T,row.names = 1)
positive.ions.zscores<-read.csv("../Data/Metabolic_profiles/Fuhrer_Zampieri_et_al_data/positive_ions_zscores_gene_kos.csv",header=T,row.names = 1)
#combine all z-scores in a single matrix
all.ions.zscores<-rbind(as.matrix(positive.ions.zscores),as.matrix(negative.ions.zscores))
#define threshold for top 10% absolute z-scores for arcA KO
arcA.zscore.threshold<-as.numeric(quantile(abs(all.ions.zscores[,"arcA"]),0.9))
#define vectors with arcA KO z-scores
arcA.positive.ions.zscores<-positive.ions.zscores[,"arcA"]
arcA.negative.ions.zscores<-negative.ions.zscores[,"arcA"]
#identify decreased metabolites associated with (+) ions
arcA.positive.ions.decreased<-which(arcA.positive.ions.zscores <= -1* arcA.zscore.threshold)
#map altered metabolites to their KEGG ids
arcA.positive.ions.decreased.kegg<-positive.ions.to.metabolites.map[which(positive.ions.to.metabolites.map[,"ion"] %in% arcA.positive.ions.decreased),"id"]
#identify decreased metabolites associated with (-) ions
arcA.negative.ions.decreased<-which(arcA.negative.ions.zscores <= -1* arcA.zscore.threshold)
#map altered metabolites to their KEGG ids
arcA.negative.ions.decreased.kegg<-negative.ions.to.metabolites.map[which(negative.ions.to.metabolites.map[,"ion"] %in% arcA.negative.ions.decreased),"id"]
#combine all KEGG ids
arcA.decreased.metabolites<-union(arcA.positive.ions.decreased.kegg,arcA.negative.ions.decreased.kegg)
#identify increased metabolites associated with (+) ions
arcA.positive.ions.increased<-which(arcA.positive.ions.zscores >= arcA.zscore.threshold)
#map altered metabolites to their KEGG ids
arcA.positive.ions.increased.kegg<-positive.ions.to.metabolites.map[which(positive.ions.to.metabolites.map[,"ion"] %in% arcA.positive.ions.increased),"id"]
#identify increased metabolites associated with (-) ions
arcA.negative.ions.increased<-which(arcA.negative.ions.zscores >=  arcA.zscore.threshold)
arcA.negative.ions.increased.kegg<-negative.ions.to.metabolites.map[which(negative.ions.to.metabolites.map[,"ion"] %in% arcA.negative.ions.increased),"id"]
#combine all KEGG ids
arcA.increased.metabolites<-union(arcA.negative.ions.increased.kegg,arcA.positive.ions.increased.kegg)
#save metabolite ids in a .csv file
#write.csv(file="../Data/Metabolic_profiles/Fuhrer_Zampieri_et_al_data/arcA_ko_differential_metabolites_kegg_083122.csv",union(arcA.increased.metabolites,arcA.decreased.metabolites))
#generate Fig. S7
#read MetaboAnalyst output files
metaboanalyst.output.sertraline<-read.csv("../Data/Metabolic_profiles/Campos_Zampieri_data/MetaboAnalyst_sertraline_pathway_results_08302022.csv")
metaboanalyst.output.cefpiramide<-read.csv("../Data/Metabolic_profiles/Campos_Zampieri_data/MetaboAnalyst_cefpiramide_pathway_results_08302022.csv")
metaboanalyst.output.arcA.ko<-read.csv("../Data/Metabolic_profiles/Fuhrer_Zampieri_et_al_data/MetaboAnalyst_arcA_KO_result_pathway_083122.csv")
#choose color palette for heatmap
heatmap.colors <- c("black","grey","white")
#create tables with perturbed pathways based on FDR p-values
sertraline.perturbed.pathways<-metaboanalyst.output.sertraline[which(metaboanalyst.output.sertraline[,"FDR"]<= 0.25),c("X","FDR")]
cefpiramide.perturbed.pathways<-metaboanalyst.output.cefpiramide[which(metaboanalyst.output.cefpiramide[,"FDR"]<= 0.25),c("X","FDR")]
arcA.ko.perturbed.pathways<-metaboanalyst.output.arcA.ko[which(metaboanalyst.output.arcA.ko[,"FDR"]<= 0.25),c("X","FDR")]
#create vector with altered metabolic pathways
perturbed.pathways.combined<-unique(c(as.character(sertraline.perturbed.pathways[,"X"]),as.character(cefpiramide.perturbed.pathways[,"X"]),as.character(arcA.ko.perturbed.pathways[,"X"])))
#create matrix with pathways identified as perturbed by MetaboAnalyst 
perturbed.pathways.matrix<-matrix(ncol=3,nrow=length(perturbed.pathways.combined),dimnames = list(perturbed.pathways.combined,c("arcA KO","Sertraline-treated","Cefpiramide-treated")),1)
#fill out the matrix
for(pathway in perturbed.pathways.combined)
{
  if( pathway %in% sertraline.perturbed.pathways[,"X"])
  {
    current.pathway.position<-which(sertraline.perturbed.pathways[,"X"]==pathway)
    perturbed.pathways.matrix[pathway,"Sertraline-treated"]<- sertraline.perturbed.pathways[current.pathway.position,"FDR"]
  }
  if( pathway %in% cefpiramide.perturbed.pathways[,"X"])
  {
    current.pathway.position<-which(cefpiramide.perturbed.pathways[,"X"]==pathway)
    perturbed.pathways.matrix[pathway,"Cefpiramide-treated"]<- cefpiramide.perturbed.pathways[current.pathway.position,"FDR"]
  }
  if( pathway %in% arcA.ko.perturbed.pathways[,"X"])
  {
    current.pathway.position<-which(arcA.ko.perturbed.pathways[,"X"]==pathway)
    perturbed.pathways.matrix[pathway,"arcA KO"]<- arcA.ko.perturbed.pathways[current.pathway.position,"FDR"]
  }
}
#plot heatmap
pheatmap(t(perturbed.pathways.matrix),color =heatmap.colors,scale = "none",cluster_rows=F,cluster_cols = F,fontsize = 8,angle_col = 90, breaks = c(0,0.1,0.25,1),main="Fig. S7")

5.3 Fig. 5B

#assess susceptibility of the WT, WT DarcA, TetR and TetR DarcA strains to sertraline 
#read OD readings from Bioscreen experiments to generate corresponding growth curves
#first, read growth data for WT and WT DarcA treated with a range of sertraline concentrations 
#for each strain/sertraline concentration, there were three biological replicates (each one with three replicates)
#bioscreen experiment was performed for a total of ~25h
#WT strain was cultured in plate # 1 (ie, wells #1-100)
#WT DarcA strain was cultured in plate # 2 (ie, wells #101-200)
growth.data.WT.WTarcA.sertraline<-read.csv("../Data/Sertraline_dilution/WT_and_WT arcA/2022_0222_formatted_data.csv",row.names=1)
#normalize data by subtracting minimum OD reading per well 
#normalized matrix includes the first ~16h of growth
growth.data.WT.WTarcA.sertraline.16h.normalized<-c()
for(i in 1:ncol(growth.data.WT.WTarcA.sertraline))
{
  minimum.reading.current.well<-min(growth.data.WT.WTarcA.sertraline[1:33,i])
  growth.data.WT.WTarcA.sertraline.16h.normalized<-cbind(growth.data.WT.WTarcA.sertraline.16h.normalized,growth.data.WT.WTarcA.sertraline[1:33,i]-minimum.reading.current.well)
}
#add column names
colnames(growth.data.WT.WTarcA.sertraline.16h.normalized)<-colnames(growth.data.WT.WTarcA.sertraline)
#define maximum OD among blank wells (wells # 92-100 were included as a control for WT, and wells # 192-200 as a control for WT arcA) 
#1st OD reading was excluded in this analysis because it commonly gives a higher than expected reading (ie, higher than the reading taken a few minutes later)
wt.max.blank<-max(growth.data.WT.WTarcA.sertraline.16h.normalized[-1,92:100])
wt.arcA.max.blank<-max(growth.data.WT.WTarcA.sertraline.16h.normalized[-1,192:200])
#define wells where growth was observed as those where max OD > 2x maximum growth detected in blank wells (inoculated with sterile LB)
wt.wells.that.grew<-names(which(apply(FUN=max, MARGIN = 2,growth.data.WT.WTarcA.sertraline.16h.normalized[-1,2:90])>2*wt.max.blank))
wt.arcA.wells.that.grew<-names(which(apply(FUN=max, MARGIN = 2,growth.data.WT.WTarcA.sertraline.16h.normalized[-1,102:190])>2*wt.arcA.max.blank))
#estimate WT MIC for sertraline
wt.sertraline.concentrations<-paste("WT_",c(0,seq(30,60,by=5),80),sep="")
#define default MIC as the highest concentration that was tested
wt.sertraline.mic<-80
for(wt.conc in wt.sertraline.concentrations)
{
temporal.concentration<-as.numeric(strsplit(wt.conc,split="_")[[1]][2])
if (length(grep(wt.conc,wt.wells.that.grew))<2 & temporal.concentration < wt.sertraline.mic)
{
  wt.sertraline.mic<-temporal.concentration
}
}
#estimate WT DarcA MIC for sertraline
wt.arcA.sertraline.concentrations<-paste("WTarcA_",c(0,seq(30,60,by=5),80),sep="") #values in ug/ml
#default MIC value
wt.arcA.sertraline.mic<-80
for(wt.arcA.conc in wt.arcA.sertraline.concentrations)
{
temporal.concentration<-as.numeric(strsplit(wt.arcA.conc,split="_")[[1]][2])
if (length(grep(wt.arcA.conc,wt.arcA.wells.that.grew))<2 & temporal.concentration < wt.arcA.sertraline.mic)
{
  wt.arcA.sertraline.mic<-temporal.concentration
}
}
print(paste("WT Sertraline MIC:",wt.sertraline.mic,"ug/ml",sep=""))
[1] "WT Sertraline MIC:45ug/ml"
print(paste("WT DarcA Sertraline MIC:",wt.arcA.sertraline.mic,"ug/ml",sep=""))
[1] "WT DarcA Sertraline MIC:50ug/ml"
#second, read growth data for TetR and TetR DarcA treated with different sertraline concentrations 
#experiment was performed for a total of ~24h
#TetR strain was cultured in plate # 1 (ie, wells #1-100)
#TetR DarcA strain was cultured in plate # 2 (ie, wells #101-200)
growth.data.TetR.TetRarcA.sertraline<-read.csv("../Data/Sertraline_dilution/TetR_and_TetR arcA/2022_0221_formatted_data.csv",row.names=1)
#normalize data by subtracting minimum OD reading per well
#normalized matrix includes the first ~16h of growth
growth.data.TetR.TetRarcA.sertraline.16h.normalized<-c()
for(i in 1:ncol(growth.data.TetR.TetRarcA.sertraline))
{
  minimum.reading.current.well<-min(growth.data.TetR.TetRarcA.sertraline[1:33,i])
  growth.data.TetR.TetRarcA.sertraline.16h.normalized<-cbind(growth.data.TetR.TetRarcA.sertraline.16h.normalized,                                    growth.data.TetR.TetRarcA.sertraline[1:33,i]-minimum.reading.current.well)
}
#add column names
colnames(growth.data.TetR.TetRarcA.sertraline.16h.normalized)<-colnames(growth.data.TetR.TetRarcA.sertraline)
#define maximum OD among blank wells (wells # 92-100 were included as a control for TetR, and wells # 192-200 as a control for TetR arcA) 
tetR.max.blank<-max(growth.data.TetR.TetRarcA.sertraline.16h.normalized[-1,92:100])
tetR.arcA.max.blank<-max(growth.data.TetR.TetRarcA.sertraline.16h.normalized[-1,192:200])
#define wells where growth was observed as those where max OD > 2x maximum growth detected in blank wells (inoculated with sterile LB)
tetR.wells.that.grew<-names(which(apply(FUN=max, MARGIN = 2,growth.data.TetR.TetRarcA.sertraline.16h.normalized[-1,2:90])>2*tetR.max.blank))
tetR.arcA.wells.that.grew<-names(which(apply(FUN=max, MARGIN = 2,growth.data.TetR.TetRarcA.sertraline.16h.normalized[-1,102:190])>2*tetR.arcA.max.blank))
#estimate TetR MIC for sertraline
tetR.sertraline.concentrations<-paste("TetR_",c(0,seq(20,50,by=5),60),sep="")
#default value
tetR.sertraline.mic<-60
for(tetR.conc in tetR.sertraline.concentrations)
{
temporal.concentration<-as.numeric(strsplit(tetR.conc,split="_")[[1]][2])
if (length(grep(tetR.conc,tetR.wells.that.grew))<2 & temporal.concentration < tetR.sertraline.mic)
{
  tetR.sertraline.mic<-temporal.concentration
}
}
#define TetR DarcA MIC for sertraline
tetR.arcA.sertraline.concentrations<-paste("TetRarcA_",c(0,5,seq(10,20,by=2.5),25,30),sep="") #values in ug/ml
#default MIC value
tetR.arcA.sertraline.mic<-30
for(tetR.arcA.conc in tetR.arcA.sertraline.concentrations)
{
temporal.concentration<-as.numeric(strsplit(tetR.arcA.conc,split="_")[[1]][2])
if (length(grep(tetR.arcA.conc,tetR.arcA.wells.that.grew))<2 & temporal.concentration < tetR.arcA.sertraline.mic)
{
  tetR.arcA.sertraline.mic<-temporal.concentration
}
}
print(paste("TetR Sertraline MIC:",tetR.sertraline.mic,"ug/ml",sep=""))
[1] "TetR Sertraline MIC:35ug/ml"
print(paste("TetR DarcA Sertraline MIC:",tetR.arcA.sertraline.mic,"ug/ml",sep=""))
[1] "TetR DarcA Sertraline MIC:17.5ug/ml"
#create Fig. 5B
#create vector with all sertraline concentrations (ug/ml) tested among the four strains
sertraline.concentrations<-c(0,5,10,12.5,15,17.5,20,25,30,35,40,45,50,55,60,80)
#define growth pattern (1= growth, 0= no growth, -1: not tested) of each strain in the full range of sertraline concentrations 
tetR.dose.response<-c(1,rep(-1,5),rep(1,3),rep(0,4),-1, 0,-1)
tetR.arcA.dose.response<-c(rep(1,5),rep(0,4), rep(-1,7))
wt.dose.response<-c(1, rep(-1,7),rep(1,3),rep(0,5))
wt.arcA.dose.response<- c(1, rep(-1,7),rep(1,4),rep(0,4))
#create dose response matrix
sertraline.dose.response.matrix<-cbind(wt.dose.response, wt.arcA.dose.response, 
                             tetR.dose.response,tetR.arcA.dose.response)
rownames(sertraline.dose.response.matrix)<-sertraline.concentrations
colnames(sertraline.dose.response.matrix)<-c("WT","WT arcA", "TetR","TetR arcA")
heatmap.breaks<-c(-1,-0.33,0.33,1)
pheatmap(sertraline.dose.response.matrix[16:1,],scale="none",color= c("grey","#BEAED4","#7FC97F"),
         cluster_rows=F,cluster_cols = F,fontsize = 11,angle_col = 45, breaks = heatmap.breaks,
         legend_breaks=heatmap.breaks,legend=T,main="Fig. 5B",annotation_row = )

5.4 Compute FIC2 scores of WT for the sertraline-tetracycline combination

#analyze results of DiaMOND assay for the sertraline-tetracycline combination
#function to create a monotonically decreasing dose response curve (as described in the original DiaMOND manuscript, Cokol et al. Science Advances 2017)
create.monotonically.decreasing.vector<-function(od.vector)
{
  output.vector<-c(od.vector[1])
  for(i in 2:length(od.vector))
  {
    current.point<-od.vector[i]
    if(current.point<= od.vector[i-1] & current.point <= output.vector[i-1])
    {
      output.vector<-c(output.vector,current.point)
    }
    else{
      output.vector<-c(output.vector,output.vector[i-1])
    }
  }
  output.vector
}
#function to normalize OD vector at a given time point with respect to an untreated control (initial point)
normalize.vector<-function(od.vector)
{
  output.vector<-od.vector/od.vector[1]
  output.vector
}
#function to interpolate IC50 values
interpolate.ic50<-function(normalized.od.vector,abx.concentration.range)
{
  #abx.concentration.range is the set of antibiotic concentrations associated with the dose response vector (ie, the normalized od vector)
  #confirm that the normalized vector contains values above and below 0.5 (ie, the IC50 point)
  positions.below.ic50<-which(normalized.od.vector < 0.5)
  positions.above.ic50<-which(normalized.od.vector > 0.5)
  if(length(positions.below.ic50)>0 & length(positions.above.ic50)>0)
  {
    #spline fitting
    temporal.spline.fitting<-spline(abx.concentration.range, normalized.od.vector, n=10000000)
    #estimate IC50
    estimated.ic50<-temporal.spline.fitting$x[which(abs(temporal.spline.fitting$y-0.5)==min(abs(temporal.spline.fitting$y-0.5)))]
  }
  estimated.ic50
}
#analyze DiaMOND results for WT and WT DarcA strains
#data is in a matrix with 384 columns (each column is a well in the plate)
wt.wt.arcA.biotek.data<-read.csv("../Data/DiaMOND_assay/Sertraline_Tetracycline/WT_and_WT arcA/2022_0226_formatted_data.CSV",row.names=1)
#in the 384 well plate:
#rows # 1-5 were used for sertraline linear dilutions (ie, 0x-2x by 0.2 increments)
#rows # 6-10 were used for tetracycline linear dilutions (ie, 0x-2x by 0.2 increments)
#rows # 11-15 were used for sertraline-tetracycline combination linear dilutions (ie, 0x-2x by 0.2 increments)
#columns #1 and #24 were blank (LB only) 
#columns #2-12 were inoculated with WT and columns # 13-23 were inoculated with WT arcA KO 
#remove column with temperature data
wt.wt.arcA.biotek.data<-wt.wt.arcA.biotek.data[,-1]
#define difference in OD (delta OD) for each well after 16h of growth (max OD - min OD)
#the 16h growth window was defined based on the DiaMOND protocol (Cokol-Cakmak et al. JOVE 2018)
wt.wt.arcA.biotek.delta.od<-c()
for(c in 1:ncol(wt.wt.arcA.biotek.data))
{
  wt.wt.arcA.biotek.delta.od<-c(wt.wt.arcA.biotek.delta.od,                  max(wt.wt.arcA.biotek.data[1:33,c])-min(wt.wt.arcA.biotek.data[1:33,c]))
}
names(wt.wt.arcA.biotek.delta.od)<-colnames(wt.wt.arcA.biotek.data)
#extract delta OD values for WT strain
wt.delta.od.matrix<-c()
#one row will correspond to a linear dilution (from 0x to 2x by 0.2x increments)
for(l in LETTERS[1:15])
{
  selected.wells<-paste(l,2:12,sep="")
  wt.delta.od.matrix<-rbind(wt.delta.od.matrix,wt.wt.arcA.biotek.delta.od[selected.wells])
}
#check delta OD profile and interpolate IC50s
par(mfrow=c(3,3))
wt.ic50.vector<-c()
concentration.linear.range<-seq(0,2,by=0.2)
for(r in 1:nrow(wt.delta.od.matrix))
{
  #generate monotonically decreasing delta OD vector
  current.od.vector<-create.monotonically.decreasing.vector(wt.delta.od.matrix[r,])
  #plot delta OD data (ie, effect of treatment on growth)
  if(r <6)
  {
  plot(x=concentration.linear.range,y=normalize.vector(current.od.vector),type="o",
       xlab="[Sertraline(x IC50)]",ylab='Normalized OD')
  abline(h=0.5,col="grey",lty=2)
  }
  if(r >5 & r <11)
  {
    plot(x=concentration.linear.range,y=normalize.vector(current.od.vector),type="o",
         xlab="[Tetracycline(x IC50)]",ylab='Normalized OD')
    abline(h=0.5,col="grey",lty=2)
  }
  if(r >10)
  {
    plot(x=concentration.linear.range,y=normalize.vector(current.od.vector),type="o",
         xlab="[Tetracycline-Sertraline(x IC50)]",ylab='Normalized OD')
    abline(h=0.5,col="grey",lty=2)
  }
  #define IC50 using the approxfun function
  temporal.approx.func.output<-approxfun(x=normalize.vector(current.od.vector),y=concentration.linear.range)
  ic50.interpolated.value<-temporal.approx.func.output(0.5)
  #add estimated IC50 to figure
  points(x=ic50.interpolated.value,y=0.5,col="red",pch=2)
  #save estimated IC50
  wt.ic50.vector<-c(wt.ic50.vector,round(ic50.interpolated.value,digits=3))
}

collapsing to unique 'x' values

#define WT FIC2 for each biological replicate
wt.fic<-c()
for(i in 1:5)
{
  wt.fic<-c(wt.fic,wt.ic50.vector[i+10]/(2*(wt.ic50.vector[i]*wt.ic50.vector[i+5])/(wt.ic50.vector[i]+wt.ic50.vector[i+5])))
}
print(paste("WT FIC2:",round(geoMean(wt.fic),digits = 3),sep=""))
[1] "WT FIC2:1.269"

5.5 Compute FIC2 scores of WT arcA for the sertraline-tetracycline combination

#extract delta OD values for the WT arcA strain
wt.arcA.delta.od.matrix<-c()
for(l in LETTERS[1:15])
{
  selected.wells<-paste(l,13:23,sep="")
  wt.arcA.delta.od.matrix<-rbind(wt.arcA.delta.od.matrix,wt.wt.arcA.biotek.delta.od[selected.wells])
}
#check delta OD profile and interpolate IC50s
par(mfrow=c(3,3))
wt.arcA.ic50.vector<-c()
for(r in 1:nrow(wt.arcA.delta.od.matrix))
{
  #generate monotonically decreasing delta OD vector
  current.od.vector<-create.monotonically.decreasing.vector(wt.arcA.delta.od.matrix[r,])
  #plot delta OD data
   if(r <6)
  {
  plot(x=concentration.linear.range,y=normalize.vector(current.od.vector),type="o",
       xlab="[Sertraline(x IC50)]",ylab='Normalized OD')
  abline(h=0.5,col="red",lty=2)
  }
  if(r >5 & r < 11)
  {
    plot(x=concentration.linear.range,y=normalize.vector(current.od.vector),type="o",
         xlab="[Tetracycline(x IC50)]",ylab='Normalized OD')
    abline(h=0.5,col="red",lty=2)
  }
  if(r>10)
  {
    plot(x=concentration.linear.range,y=normalize.vector(current.od.vector),type="o",
         xlab="[Sertraline-Tetracycline(x IC50)]",ylab='Normalized OD')
    abline(h=0.5,col="red",lty=2)
  }
  #define IC50 using the approxfun function
  temporal.approx.func<-approxfun(x=normalize.vector(current.od.vector),y=concentration.linear.range)
  ic50.interpolated.value<-temporal.approx.func(0.5)
  #add estimated IC50 to figure
  points(x=ic50.interpolated.value,y=0.5,col="red",pch=2)
  #save estimated IC50
  wt.arcA.ic50.vector<-c(wt.arcA.ic50.vector,round(ic50.interpolated.value,digits=3))
}

collapsing to unique 'x' values

#compute FIC2 of WT arcA replicates
wt.arcA.fic<-c()
for(i in 1:5)
{
  wt.arcA.fic<-c(wt.arcA.fic,wt.arcA.ic50.vector[i+10]/(2*(wt.arcA.ic50.vector[i]*wt.arcA.ic50.vector[i+5])/(wt.arcA.ic50.vector[i]+wt.arcA.ic50.vector[i+5])))
}
print(paste("WT arcA FIC2:",round(geoMean(wt.arcA.fic),digits=3),sep=""))
[1] "WT arcA FIC2:1.228"

5.6 Compute FIC2 of TetR arcA for the sertraline-tetracycline combination

#analyze DiaMOND results of the TetR and TetR DarcA strains
#data is in a matrix with 384 columns (each column is a well in a plate)
tetR.tetR.arcA.biotek.data<-read.csv("../Data/DiaMOND_assay/Sertraline_Tetracycline/TetR_and_TetR arcA/run1/2022_0301_formatted_data.CSV",row.names=1)
#in the 384 well plate:
#rows # 1-5 were used for sertraline linear dilutions (ie, 0x-2x by 0.2 increments)
#rows # 6-10 were used for tetracycline linear dilutions (ie, 0x-2x by 0.2 increments)
#rows # 11-15 were used for sertraline-tetracycline combination linear dilutions (ie, 0x-2x by 0.2 increments)
#columns #1 and #24 were blank (LB only) 
#columns #2-12 were inoculated with TetR and columns # 13-23 were inoculated with TetR arcA KO 
#remove column with temperature data
tetR.tetR.arcA.biotek.data<-tetR.tetR.arcA.biotek.data[,-1]
#define difference in OD (delta OD) for each well after 16h of growth (max OD - min OD)
#the 16h growth window was defined based on the DiaMOND protocol (Cokol-Cakmak et al. JOVE 2018)
tetR.tetR.arcA.delta.od<-c()
for(c in 1:ncol(tetR.tetR.arcA.biotek.data))
{
  tetR.tetR.arcA.delta.od<-c(tetR.tetR.arcA.delta.od,                            max(tetR.tetR.arcA.biotek.data[1:33,c])-min(tetR.tetR.arcA.biotek.data[1:33,c]))
}
names(tetR.tetR.arcA.delta.od)<-colnames(tetR.tetR.arcA.biotek.data)
#extract delta OD values for TetR arcA strain
tetR.arcA.delta.od.matrix<-c()
#one row will correspond to a linear dilution (from 0x to 2x by 0.2x increments)
for(l in LETTERS[1:15])
{
  selected.wells<-paste(l,13:23,sep="")
  tetR.arcA.delta.od.matrix<-rbind(tetR.arcA.delta.od.matrix,tetR.tetR.arcA.delta.od[selected.wells])
}
#check delta OD profile and interpolate IC50s
par(mfrow=c(3,3))
tetR.arcA.ic50.vector<-c()
for(r in 1:nrow(tetR.arcA.delta.od.matrix))
{
  #generate monotonically decreasing delta OD vector
  current.od.vector<-create.monotonically.decreasing.vector(tetR.arcA.delta.od.matrix[r,])
  if(r<6)
  {
  plot(x=concentration.linear.range,y=normalize.vector(current.od.vector),type="o",
       xlab="[Sertraline(x IC50)]",ylab='Normalized OD')
  abline(h=0.5,col="red",lty=2)
  }
  if(r>5 & r<11)
  {
    plot(x=concentration.linear.range,y=normalize.vector(current.od.vector),type="o",
         xlab="[Tetracycline(x IC50)]",ylab='Normalized OD')
    abline(h=0.5,col="red",lty=2)
  }
  if(r>10)
  {
    plot(x=concentration.linear.range,y=normalize.vector(current.od.vector),type="o",
         xlab="[Sertraline-Tetracycline(x IC50)]",ylab='Normalized OD')
    abline(h=0.5,col="red",lty=2)
  }
  #define IC50 using the approxfun function
  temporal.approx.func<-approxfun(x=normalize.vector(current.od.vector),y=concentration.linear.range)
  ic50.interpolated.value<-temporal.approx.func(0.5)
  #add estimated IC50 to figure
  points(x=ic50.interpolated.value,y=0.5,col="red",pch=2)
  #save estimated IC50
  tetR.arcA.ic50.vector<-c(tetR.arcA.ic50.vector,round(ic50.interpolated.value,digits=3))
}

#define FIC2 for TetR arcA replicates
tetR.arcA.fic<-c()
for(i in 1:5)
{
  tetR.arcA.fic<-c(tetR.arcA.fic,tetR.arcA.ic50.vector[i+10]/(2*(tetR.arcA.ic50.vector[i]*tetR.arcA.ic50.vector[i+5])/(tetR.arcA.ic50.vector[i]+tetR.arcA.ic50.vector[i+5])))
}
print(paste("TetR arcA FIC2:",round(geoMean(tetR.arcA.fic),digits=3),sep=""))
[1] "TetR arcA FIC2:1.2"

5.7 Compute FIC2 of TetR

#extract delta OD values for TetR strain
#NOTE:replicates with more than one potential IC50 (on the raw data) or increased growth after potential IC50 were not used for FIC2 calculation
tetR.delta.od.matrix<-c()
for(l in LETTERS[1:15])
{
  selected.wells<-paste(l,2:12,sep="")
  tetR.delta.od.matrix<-rbind(tetR.delta.od.matrix,tetR.tetR.arcA.delta.od[selected.wells])
}
#check delta OD profile and interpolate IC50s
par(mfrow=c(3,3))
tetR.ic50.vector<-c()
for(r in 1:nrow(tetR.delta.od.matrix))
{
  #generate monotonically decreasing delta OD vector
  current.od.vector<-create.monotonically.decreasing.vector(tetR.delta.od.matrix[r,])
  #we first plot the raw dose-response curve (black line)
  if(r<6)
  {
    plot(x=concentration.linear.range,y=normalize.vector(tetR.delta.od.matrix[r,]),type="l", xlab="[Sertraline(x IC50)]",ylab='Normalized OD',main="Expt1")
    abline(h=0.5,col="red",lty=2)
  }
  if(r>5 & r<11)
  {
    plot(x=concentration.linear.range,y=normalize.vector(tetR.delta.od.matrix[r,]),type="l",xlab="[Tetracycline(x IC50)]",ylab='Normalized OD',main="Expt1")
    abline(h=0.5,col="red",lty=2)
  }
  if(r>10)
  {
    plot(x=concentration.linear.range,y=normalize.vector(tetR.delta.od.matrix[r,]),type="l", xlab="[Sertraline-Tetracycline(x IC50)]",ylab='Normalized OD',main="Expt1")
    abline(h=0.5,col="red",lty=2)
  }
  #also plot monotonically decreasing dose response curve (orange line)
  points(x=concentration.linear.range,y=normalize.vector(current.od.vector),type="o",col="orange")
  #define IC50 using the in-house spline fitting function (more accurate than approxfun)
  ic50.interpolated.value<-interpolate.ic50(normalize.vector(current.od.vector),concentration.linear.range)
  #add estimated IC50 to figure
  points(x=ic50.interpolated.value,y=0.5,col="red",pch=2)
  #save estimated IC50
  tetR.ic50.vector<-c(tetR.ic50.vector,round(ic50.interpolated.value,digits=3))
}

#replicates # 1, #3 and #4 not used for FIC2 estimation after visual inspection of the sertraline dose response curves 
#a second experiment (below) was performed  to increase the number of biological replicates
#define FIC2 of TetR replicates in experiment # 1
tetR.fic.expt1<-c()
for(i in 1:5)
{
  tetR.fic.expt1<-c(tetR.fic.expt1,tetR.ic50.vector[i+10]/(2*(tetR.ic50.vector[i]*tetR.ic50.vector[i+5])/(tetR.ic50.vector[i]+tetR.ic50.vector[i+5])))
}
tetR.fic.expt1<-tetR.fic.expt1[c(2,5)]
#read data collected on a second DiaMOND experiment for TetR (five biological replicates)
tetR.biotek.data.expt2<-read.csv("../Data/DiaMOND_assay/Sertraline_Tetracycline/TetR_and_TetR arcA/run2/2022_0413_formatted_data.CSV",row.names=1)
#in the 384 well plate:
#rows # 1-5 were used for sertraline linear dilutions (0x,.2x,.4x,.6x,.8x,1.0x,1.2x,1.6x,1.4x,1.8x,2.0x))
#rows # 6-10 were used for tetracycline linear dilutions (ie, 0x-2x by 0.2 increments)
#rows # 11-15 were used for sertraline-tetracycline combination linear dilutions (ie, 0x-2x by 0.2 increments)
#columns #1, #13-15 were blank (LB only) 
#columns #2-12 were inoculated with TetR 
#remove column with temperature data
tetR.biotek.data.expt2<-tetR.biotek.data.expt2[,-1]
#extract delta OD values 
tetR.biotek.delta.od.expt2<-c()
for(c in 1:ncol(tetR.biotek.data.expt2))
{
  tetR.biotek.delta.od.expt2<-c(tetR.biotek.delta.od.expt2,                                 max(tetR.biotek.data.expt2[1:33,c])-min(tetR.biotek.data.expt2[1:33,c]))
}
names(tetR.biotek.delta.od.expt2)<-colnames(tetR.biotek.data.expt2)
#define tetR delta OD matrix (expt #2)
tetR.delta.od.matrix.expt2<-c()
for(l in LETTERS[1:15])
{
  selected.wells<-paste(l,2:12,sep="")
  tetR.delta.od.matrix.expt2<-rbind(tetR.delta.od.matrix.expt2,tetR.biotek.delta.od.expt2[selected.wells])
}
#check delta OD profile and interpolate IC50s
par(mfrow=c(3,3))

tetR.ic50.vector.expt2<-c()
for(r in 1:nrow(tetR.delta.od.matrix.expt2))
{
  #generate monotonically decreasing delta OD vector
  current.od.vector<-create.monotonically.decreasing.vector(tetR.delta.od.matrix.expt2[r,])
  if(r<6)
  {
    plot(x=concentration.linear.range[c(1:7,9,8,10:11)],y=normalize.vector(tetR.delta.od.matrix.expt2[r,c(1:7,9,8,10:11)]),type="l",
         xlab="[Sertraline(x IC50)]",ylab='Normalized OD',main="Expt2")
    abline(h=0.5,col="red",lty=2)
  }
  if(r>5 & r<11)
  {
    plot(x=concentration.linear.range,y=normalize.vector(tetR.delta.od.matrix.expt2[r,]),type="l",
         xlab="[Tetracycline(x IC50)]",ylab='Normalized OD',main="Expt2")
    abline(h=0.5,col="red",lty=2)
  }
  if(r>10)
  {
    plot(x=concentration.linear.range,y=normalize.vector(tetR.delta.od.matrix.expt2[r,]),type="o",
         xlab="[Sertraline-Tetracycline(x IC50)]",ylab='Normalized OD',main="Expt2")
    abline(h=0.5,col="red",lty=2)
  }
  #also plot monotonically decreasing version of the dose response
  points(x=concentration.linear.range,y=normalize.vector(current.od.vector),type="o",col="orange")
  #define IC50 using the in-house spline fitting function
  ic50.interpolated.value<-interpolate.ic50(normalize.vector(current.od.vector),concentration.linear.range)
  #add estimated IC50 to figure
  points(x=ic50.interpolated.value,y=0.5,col="red",pch=2)
  #save estimated IC50
  tetR.ic50.vector.expt2<-c(tetR.ic50.vector.expt2,round(ic50.interpolated.value,digits=3))
}

#define FIC2 of TetR replicates in expt # 2
tetR.fic.expt2<-c()
for(i in 1:5)
{
  tetR.fic.expt2<-c(tetR.fic.expt2,tetR.ic50.vector.expt2[i+10]/(2*(tetR.ic50.vector.expt2[i]*tetR.ic50.vector.expt2[i+5])/(tetR.ic50.vector.expt2[i]+tetR.ic50.vector.expt2[i+5])))
}
#remove 5th replicate
tetR.fic.expt2<-tetR.fic.expt2[1:4]
#combine TetR FIC2 from both experiments
tetR.fic<-union(tetR.fic.expt1,tetR.fic.expt2)
print(paste("TetR FIC2:",round(geoMean(tetR.fic),digits=3),sep=""))
[1] "TetR FIC2:0.669"

5.8 Fig. 5C

boxplot(wt.fic,wt.arcA.fic,tetR.fic,tetR.arcA.fic,
        col=strain.colors[1:4],
        names=c("WT","WT arcA", "TetR","TetR arcA"),las=2,
        cex.axis=1.1,cex.lab=1.1,ylab="FIC2",ylim=c(0.5,1.3),main="Fig. 5C")
abline(h=1,col="darkgrey",lty=2)

LS0tCnRpdGxlOiAiQ29tcHV0YXRpb25hbCBhbmFseXNlcyBmb3IgKkRpc3J1cHRpbmcgdGhlIEFyY0EgcmVndWxhdG9yeSBuZXR3b3JrIGFtcGxpZmllcyB0aGUgZml0bmVzcyBjb3N0IG9mIHRldHJhY3ljbGluZSByZXNpc3RhbmNlIGluIEVzY2hlcmljaGlhIGNvbGkqIG1hbnVzY3JpcHQiCm91dHB1dDogaHRtbF9ub3RlYm9vawphdXRob3I6IE1hcmlvIEFycmlldGEtT3J0aXogZXQgYWwuCmRhdGU6IFNlcHRlbWJlciA3LCAyMDIyCi0tLQowLiBMb2FkIHJlcXVpcmVkIGxpYnJhcmllcwpgYGB7ciBtZXNzYWdlPUZBTFNFfQpsaWJyYXJ5KEFMREV4MikKbGlicmFyeShjb3JwY29yKQpsaWJyYXJ5KEVudlN0YXRzKQpsaWJyYXJ5KGdkYXRhKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZ3Bsb3RzKQpsaWJyYXJ5KGdyaWRFeHRyYSkKbGlicmFyeShncm93dGhjdXJ2ZXIpCmxpYnJhcnkoaWdyYXBoKQpsaWJyYXJ5KG11bHR0ZXN0KQpsaWJyYXJ5KG5ldHdvcmspCmxpYnJhcnkocGx5cikKbGlicmFyeShwaGVhdG1hcCkKbGlicmFyeShSQ29sb3JCcmV3ZXIpCmxpYnJhcnkoUnRzbmUpCmxpYnJhcnkodmlyaWRpcykKYGBgCjEuMSBMb2FkIGdlbm9tZSBhbm5vdGF0aW9uIHJlbGF0ZWQgdG8gZWZmbHV4IHB1bXBzLCBtZXRhYm9saXNtIGFuZCB0cmFuc2NyaXB0aW9uYWwgcmVndWxhdGlvbiAoY29tcGlsZWQgZnJvbSBtdWx0aXBsZSBzb3VyY2VzKQpgYGB7cn0KI2xvYWQgdHJhbnNjcmlwdGlvbmFsIHJlZ3VsYXRvcnkgbmV0d29yayBjb21waWxlZCBmcm9tIFJlZ3Vsb25EQiAoaHR0cDovL3JlZ3Vsb25kYi5jY2cudW5hbS5teCkKI3Jvd3MgYXJlIHRhcmdldCBnZW5lcyBhbmQgY29sdW1ucyBhcmUgcmVndWxhdG9ycwojYWN0aXZhdGlvbiBhbmQgcmVwcmVzc2lvbiBhcmUgaW5kaWNhdGVkIHdpdGggJzEnIGFuZCAnLTEnLCByZXNwZWN0aXZlbHkKbG9hZCgiLi4vRGF0YS9JbnB1dC9FY29saV9UUk4uUkRhdGEiKQojZGVmaW5lIHRyYW5zY3JpcHRpb24gZmFjdG9yIChURikgbmFtZXMKdGYubmFtZXM8LWNvbG5hbWVzKHRyYW5zY3JpcHRpb25hbC5uZXR3b3JrKQoja2VlcCBvbmx5IGxvY3VzIHRhZ3MgZm9yIFRGIG5hbWVzIChmb3JtYXQgaXMgbG9jdXNfbmFtZSkKdGYubmFtZXM8LXNhcHBseSgxOmxlbmd0aCh0Zi5uYW1lcyksZnVuY3Rpb24oeCl7c3Ryc3BsaXQodGYubmFtZXNbeF0sc3BsaXQ9Il8iKVtbMV1dWzJdfSkKI3JlYWQgbmFtZXMgb2YgbWV0YWJvbGljIGdlbmVzIG9uIHRoZSBFLiBjb2xpIG1ldGFib2xpYyBtb2RlbCBpSk8xMzY2IChPcnRoIGV0IGFsLiAyMDExLCBNU0IpCm1ldGFib2xpYy5nZW5lczwtcmVhZC5jc3YoIi4uL0RhdGEvSW5wdXQvZ2VuZXNfbWV0YWJvbGljX21vZGVsX2lKTzEzNjYuY3N2IikKbWV0YWJvbGljLmdlbmVzPC1tZXRhYm9saWMuZ2VuZXMkTW9kZWwuZ2VuZXMKI3JlYWQgZWZmbHV4IHB1bXAgcmVsYXRlZCBnZW5lcyAoY29tcGlsZWQgZnJvbSBFY29DeWMgZGF0YWJhc2UgYW5kIGxpdGVyYXR1cmUgcmV2aWV3KQplZmZsdXhQdW1wLmdlbmVzPC1yZWFkLmNzdigiLi4vRGF0YS9JbnB1dC9lZmZsdXhfcHVtcF9nZW5lcy5jc3YiLGhlYWRlcj1UKQplZmZsdXhQdW1wLmdlbmVzPC1lZmZsdXhQdW1wLmdlbmVzJExvY3VzCiNleGNsdWRlIFRGcyBhbmQgZWZmbHV4IHB1bXAgcmVsYXRlZCBnZW5lcyBmcm9tIHRoZSBtZXRhYm9saWMgY2F0ZWdvcnkKbWV0YWJvbGljLmdlbmVzPC1zZXRkaWZmKG1ldGFib2xpYy5nZW5lcyx1bmlvbih0Zi5uYW1lcyxlZmZsdXhQdW1wLmdlbmVzKSkKI2NyZWF0ZSBmdW5jdGlvbiB0byBjb252ZXJ0IGxvY3VzIHRhZyB0byBzdGFuZGFyZCBnZW5lIG5hbWUgKGUuZy4sIGIwMDAxIHRvIHRockwpCmVjb2xpLnRybi5nZW5lczwtcm93bmFtZXModHJhbnNjcmlwdGlvbmFsLm5ldHdvcmspCmNvbnZlcnQubG9jdXMudG8uZ2VuZS5uYW1lPC1mdW5jdGlvbihsb2N1cy5saXN0KQp7CiAgb3V0cHV0PC1zYXBwbHkoMTpsZW5ndGgobG9jdXMubGlzdCksZnVuY3Rpb24oeCl7c3Ryc3BsaXQoZWNvbGkudHJuLmdlbmVzW2dyZXAobG9jdXMubGlzdFt4XSxlY29saS50cm4uZ2VuZXMpXSxzcGxpdD0iXyIpW1sxXV1bMV19KQogIG91dHB1dAp9CmBgYAoxLjIgUnVuIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2lzIG9mIHRyYW5zY3JpcHRpb25hbCBkYXRhIHJlcG9ydGVkIGJ5IEhhbmRlbCBldCBhbC4gKDIwMTQpCmBgYHtyfQojcGVyZm9ybSBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhbmFseXNpcyB3aXRoIGEgQmF5ZXNpYW4gdC10ZXN0IHVzaW5nIEN5YmVyLVQgYWxnb3JpdGhtIChCYWxkaSBhbmQgTG9uZywgMjAwMSkKI2NvZGUgZG93bmxvYWRlZCBmcm9tIGh0dHA6Ly9jeWJlcnQuaWNzLnVjaS5lZHUKc291cmNlKCJCYXllc2lhbl9UdGVzdC9jeWJlclR0ZXN0LlIiKQojcmVhZCBub3JtYWxpemVkIEdFTyBkYXRhIChhY2Nlc3Npb24gSUQ6IEdTRTU3MDg0KQpoYW5kZWwubm9ybWFsaXplZC5tYXRyaXg8LXJlYWQuY3N2KCIuLi9EYXRhL0RpZmZlcmVudGlhbF9leHByZXNzaW9uX2FuYWx5c2lzL0dFT19IYW5kZWwyMDE0L0hhbmRlbF9ub3JtYWxpemVkX0dFT19kYXRhLmNzdiIsaGVhZGVyPVQscm93Lm5hbWVzID0gMSkKI3JlYWQgbWFwIGJldHdlZW4gbWljcm9hcnJheSBwcm9iZSBJRHMgYW5kIGxvY2kKcHJvYmVzLnRvLmxvY2kubWFwPC1yZWFkLmNzdigiLi4vRGF0YS9EaWZmZXJlbnRpYWxfZXhwcmVzc2lvbl9hbmFseXNpcy9HRU9fSGFuZGVsMjAxNC9wcm9iZXNfbG9jaV9hcnJheV9tYXAuY3N2IixoZWFkZXIgPSBULHJvdy5uYW1lcz0xKQpwcm9iZXMudG8ubG9jaS5tYXA8LWFzLm1hdHJpeChwcm9iZXMudG8ubG9jaS5tYXApCiNyZXBsYWNlIHByb2JlIG5hbWVzIGluIGV4cHJlc3Npb24gbWF0cml4IHdpdGggbG9jdXMgdGFncwpyb3duYW1lcyhoYW5kZWwubm9ybWFsaXplZC5tYXRyaXgpPC1wcm9iZXMudG8ubG9jaS5tYXBbcm93bmFtZXMoaGFuZGVsLm5vcm1hbGl6ZWQubWF0cml4KSwiT1JGIl0KI2Z1bmN0aW9uIHRvIGNvdW50IHRoZSBudW1iZXIgb2YgVEZzLCBlZmZsdXggcHVtcCBnZW5lcyBhbmQgbWV0YWJvbGljIGdlbmVzIGFtb25nIHNpZ25pZmljYW50bHkgdXAtIGFuZCBkb3duLXJlZ3VsYXRlZCBnZW5lcwpjbGFzc2lmeS5kZWdzPC1mdW5jdGlvbihnZW5lU2V0LGV4cHJlc3Npb24uY2hhbmdlKSAKewogIG91dHB1dDwtYygpCiAgaWYoZXhwcmVzc2lvbi5jaGFuZ2U9PSJVUCIpCiAgewogICAgI2NvdW50IFRGIGdlbmVzCiAgICB1cC50ZnM8LWxlbmd0aChpbnRlcnNlY3QoZ2VuZVNldCx0Zi5uYW1lcykpCiAgICAjcHJpbnQgbmFtZXMgb2YgdXAtcmVndWxhdGVkIFRGcwogICAgaWYodXAudGZzIT0wKQogICAgewogICAgY29udmVydC5sb2N1cy50by5nZW5lLm5hbWUoaW50ZXJzZWN0KGdlbmVTZXQsdGYubmFtZXMpKQogICAgfQogICAgI2NvdW50IGVmZmx1eCBwdW1wIGdlbmVzIChlcHMpCiAgICB1cC5lcHM8LWxlbmd0aChpbnRlcnNlY3QoZ2VuZVNldCxlZmZsdXhQdW1wLmdlbmVzKSkKICAgICNwcmludCBuYW1lcyBvZiB1cC1yZWd1bGF0ZWQgZXBzCiAgICBpZih1cC5lcHMhPTApCiAgICB7CiAgICBjb252ZXJ0LmxvY3VzLnRvLmdlbmUubmFtZShpbnRlcnNlY3QoZ2VuZVNldCxlZmZsdXhQdW1wLmdlbmVzKSkKICAgIH0KICAgICNjb3VudCB1cC1yZWd1bGF0ZWQgbWV0YWJvbGljIGdlbmVzCiAgICB1cC5tZXRhYm9saWM8LWxlbmd0aChpbnRlcnNlY3QoZ2VuZVNldCxtZXRhYm9saWMuZ2VuZXMpKQogICAgI2NvdW50IG90aGVyIHVwLXJlZ3VsYXRlZCBnZW5lcwogICAgdXAub3RoZXJzPC1sZW5ndGgoZ2VuZVNldCktKHVwLnRmcyt1cC5lcHMrdXAubWV0YWJvbGljKQogICAgI2NvbXBpbGUgdmFsdWVzIGluIGEgc2luZ2xlIHZlY3RvcgogICAgb3V0cHV0PC1jYmluZCh1cC5vdGhlcnMsdXAubWV0YWJvbGljLHVwLnRmcyx1cC5lcHMpCiAgfQogICAgaWYoZXhwcmVzc2lvbi5jaGFuZ2U9PSJET1dOIikKICAgIHsKICAgICNjb3VudCBURiBnZW5lcwogICAgZG93bi50ZnM8LSAtMSpsZW5ndGgoaW50ZXJzZWN0KGdlbmVTZXQsdGYubmFtZXMpKQogICAgI3ByaW50IG5hbWVzIG9mIGRvd24tcmVndWxhdGVkIFRGcwogICAgaWYoZG93bi50ZnMhPTApCiAgICB7CiAgICBjb252ZXJ0LmxvY3VzLnRvLmdlbmUubmFtZShpbnRlcnNlY3QoZ2VuZVNldCx0Zi5uYW1lcykpCiAgICB9CiAgICAjY291bnQgZWZmbHV4IHB1bXAgZ2VuZXMgKGVwcykKICAgIGRvd24uZXBzPC0gLTEqbGVuZ3RoKGludGVyc2VjdChnZW5lU2V0LGVmZmx1eFB1bXAuZ2VuZXMpKQogICAgI3ByaW50IG5hbWVzIG9mIGRvd24tcmVndWxhdGVkIGVwcwogICAgaWYoZG93bi5lcHMhPTApCiAgICB7CiAgICBjb252ZXJ0LmxvY3VzLnRvLmdlbmUubmFtZShpbnRlcnNlY3QoZ2VuZVNldCxlZmZsdXhQdW1wLmdlbmVzKSkKICAgIH0KICAgICNjb3VudCBkb3duLXJlZ3VsYXRlZCBtZXRhYm9saWMgZ2VuZXMKICAgIGRvd24ubWV0YWJvbGljPC0gLTEqIGxlbmd0aChpbnRlcnNlY3QoZ2VuZVNldCxtZXRhYm9saWMuZ2VuZXMpKQogICAgI2NvdW50IG90aGVyIGRvd24tcmVndWxhdGVkIGdlbmVzCiAgICBkb3duLm90aGVyczwtIC0xKmxlbmd0aChnZW5lU2V0KS0oZG93bi50ZnMrZG93bi5lcHMrZG93bi5tZXRhYm9saWMpCiAgICAjY29tcGlsZSB2YWx1ZXMgaW4gYSBzaW5nbGUgdmVjdG9yCiAgICBvdXRwdXQ8LWNiaW5kKGRvd24ub3RoZXJzLGRvd24ubWV0YWJvbGljLGRvd24udGZzLGRvd24uZXBzKQogIH0KICBvdXRwdXQKfQojcnVuIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2VzIAojV1QgcmVzcG9uc2UgdG8gdGV0cmFjeWNsaW5lOiBXVCgrVEVUKSB2cyBXVCgtVEVUKSAKd3QucmVzcG9uc2U8LWJheWVzVChoYW5kZWwubm9ybWFsaXplZC5tYXRyaXhbLDE6Nl0sbnVtQyA9IDMsbnVtRSA9IDMsY29uZiA9IDcsZG9NdWx0dGVzdCA9IFQpCiNkZWZpbmUgc2V0IG9mIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyAoREVHcykKd3QucmVzcG9uc2UuZGVnczwtcm93bmFtZXMod3QucmVzcG9uc2UpW3doaWNoKHd0LnJlc3BvbnNlJEJIIDwgMC4wNSAmIGFicyh3dC5yZXNwb25zZSRtZWFuQyAtIHd0LnJlc3BvbnNlJG1lYW5FKT4xKV0KcHJpbnQocGFzdGUoIldUIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCIsbGVuZ3RoKHd0LnJlc3BvbnNlLmRlZ3MpLCJnZW5lcyBpbiByZXNwb25zZSB0byB0ZXRyYWN5Y2xpbmUiLHNlcD0iICIpKQojY3JlYXRlIHZlY3RvciB3aXRoIGZvbGQtY2hhbmdlIGZvciBhbGwgZ2VuZXMKd3QucmVzcG9uc2UuZm9sZC5jaGFuZ2U8LXd0LnJlc3BvbnNlJG1lYW5FIC0gd3QucmVzcG9uc2UkbWVhbkMKbmFtZXMod3QucmVzcG9uc2UuZm9sZC5jaGFuZ2UpPC1yb3duYW1lcyh3dC5yZXNwb25zZSkKI2RlZmluZSBzZXRzIG9mIHVwLSBhbmQgZG93bi1yZWd1bGF0ZWQgZ2VuZXMKd3QuZGVnLnVwPC13dC5yZXNwb25zZS5kZWdzW3doaWNoKHd0LnJlc3BvbnNlLmZvbGQuY2hhbmdlW3d0LnJlc3BvbnNlLmRlZ3NdPjApXQp3dC5kZWcuZG93bjwtd3QucmVzcG9uc2UuZGVnc1t3aGljaCh3dC5yZXNwb25zZS5mb2xkLmNoYW5nZVt3dC5yZXNwb25zZS5kZWdzXTwwKV0KI3dyaXRlIENTViBmaWxlcyB3aXRoIHVwLSBhbmQgZG93bi1yZWd1bGF0ZWQgZ2VuZXMgZm9yIGRvd25zdHJlYW0gYW5hbHlzaXMgb24gREFWSUQgCiN3cml0ZS5jc3YoZmlsZT0iLi4vRGF0YS9EaWZmZXJlbnRpYWxfZXhwcmVzc2lvbl9hbmFseXNpcy9EQVZJRF9lbnJpY2htZW50X2FuYWx5c2lzL0lucHV0L3d0X3Jlc3BvbnNlX3VwXzA4MDgyMi5jc3YiLHd0LmRlZy51cCxyb3cubmFtZXMgPSBGKQojd3JpdGUuY3N2KGZpbGU9Ii4uL0RhdGEvRGlmZmVyZW50aWFsX2V4cHJlc3Npb25fYW5hbHlzaXMvREFWSURfZW5yaWNobWVudF9hbmFseXNpcy9JbnB1dC93dF9yZXNwb25zZV9kb3duXzA4MDgyMi5jc3YiLHd0LmRlZy5kb3duLHJvdy5uYW1lcyA9IEYpCiNjb3VudCBURnMsIGVmZmx1eCBwdW1wcywgbWV0YWJvbGljIGdlbmVzIGFuZCBvdGhlciBnZW5lcyBpbiB0aGUgdXAtIGFuZCBkb3duLXJlZ3VsYXRlZCBnZW5lcwp1cC53dC52ZWN0b3I8LWNsYXNzaWZ5LmRlZ3Mod3QuZGVnLnVwLCJVUCIpCmRvd24ud3QudmVjdG9yPC1jbGFzc2lmeS5kZWdzKHd0LmRlZy5kb3duLCJET1dOIikKI2RpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2lzIGZvciBUZXRSIGJhc2VsaW5lIGNoYW5nZTogVGV0UigtVEVUKSB2cyBXVCgtVEVUKQp0ZXRSLmJhc2FsPC1iYXllc1QoaGFuZGVsLm5vcm1hbGl6ZWQubWF0cml4WyxjKDE6Myw3OjkpXSxudW1DID0gMyxudW1FID0gMyxjb25mID0gNyxkb011bHR0ZXN0ID0gVCkKI2RlZmluZSBERUdzCnRldFIuYmFzYWwuZGVnczwtcm93bmFtZXModGV0Ui5iYXNhbClbd2hpY2godGV0Ui5iYXNhbCRCSCA8IDAuMDUgJiBhYnModGV0Ui5iYXNhbCRtZWFuQyAtIHRldFIuYmFzYWwkbWVhbkUpPjEpXQpwcmludChwYXN0ZSgiVGV0UiAoLVRFVCkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIixsZW5ndGgodGV0Ui5iYXNhbC5kZWdzKSwiZ2VuZXMgd2l0aCByZXNwZWN0IHRvIFdUKC1URVQpIixzZXA9IiAiKSkKI3NhdmUgZm9sZC1jaGFuZ2UgZm9yIGFsbCBnZW5lcwp0ZXRSLmJhc2FsLmZvbGQuY2hhbmdlPC10ZXRSLmJhc2FsJG1lYW5FIC0gdGV0Ui5iYXNhbCRtZWFuQwpuYW1lcyh0ZXRSLmJhc2FsLmZvbGQuY2hhbmdlKTwtcm93bmFtZXModGV0Ui5iYXNhbCkKI2RlZmluZSBzZXRzIG9mIHVwLSBhbmQgZG93bi1yZWd1bGF0ZWQgZ2VuZXMKdGV0Ui5iYXNhbC5kZWdzLnVwPC10ZXRSLmJhc2FsLmRlZ3Nbd2hpY2godGV0Ui5iYXNhbC5mb2xkLmNoYW5nZVt0ZXRSLmJhc2FsLmRlZ3NdPjApXQp0ZXRSLmJhc2FsLmRlZ3MuZG93bjwtdGV0Ui5iYXNhbC5kZWdzW3doaWNoKHRldFIuYmFzYWwuZm9sZC5jaGFuZ2VbdGV0Ui5iYXNhbC5kZWdzXTwwKV0KI3dyaXRlIENTViBmaWxlcyB3aXRoIHVwLSBhbmQgZG93bi1yZWd1bGF0ZWQgZ2VuZXMgZm9yIGRvd25zdHJlYW0gYW5hbHlzaXMgb24gREFWSUQgCiN3cml0ZS5jc3YoZmlsZT0iLi4vRGF0YS9EaWZmZXJlbnRpYWxfZXhwcmVzc2lvbl9hbmFseXNpcy9EQVZJRF9lbnJpY2htZW50X2FuYWx5c2lzL0lucHV0L3RldFJfYmFzYWxfdXBfMDgwODIyLmNzdiIsdGV0Ui5iYXNhbC5kZWdzLnVwLHJvdy5uYW1lcyA9IEYpCiN3cml0ZS5jc3YoZmlsZT0iLi4vRGF0YS9EaWZmZXJlbnRpYWxfZXhwcmVzc2lvbl9hbmFseXNpcy9EQVZJRF9lbnJpY2htZW50X2FuYWx5c2lzL0lucHV0L3RldFJfYmFzYWxfZG93bl8wODA4MjIuY3N2Iix0ZXRSLmJhc2FsLmRlZ3MuZG93bixyb3cubmFtZXMgPSBGKQojY291bnQgVEZzLCBlZmZsdXggcHVtcHMsIG1ldGFib2xpYyBnZW5lcyBhbmQgb3RoZXIgZ2VuZXMgaW4gdGhlIHVwLSBhbmQgZG93bi1yZWd1bGF0ZWQgZ2VuZXMKdXAudGV0Ui5iYXNhbC52ZWN0b3I8LWNsYXNzaWZ5LmRlZ3ModGV0Ui5iYXNhbC5kZWdzLnVwLCJVUCIpCmRvd24udGV0Ui5iYXNhbC52ZWN0b3I8LWNsYXNzaWZ5LmRlZ3ModGV0Ui5iYXNhbC5kZWdzLmRvd24sIkRPV04iKQojZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gYW5hbHlzaXMgZm9yIFRldFIgcmVzcG9uc2UgdG8gdGV0cmFjeWNsaW5lOiBUZXRSKCspIHZzIFRldFIoLSkgCnRldFIucmVzcG9uc2U8LWJheWVzVChoYW5kZWwubm9ybWFsaXplZC5tYXRyaXhbLDc6MTJdLG51bUMgPSAzLG51bUUgPSAzLGNvbmYgPSA3LGRvTXVsdHRlc3QgPSBUKQojZGVmaW5lIERFR3MKdGV0Ui5yZXNwb25zZS5kZWdzPC1yb3duYW1lcyh0ZXRSLnJlc3BvbnNlKVt3aGljaCh0ZXRSLnJlc3BvbnNlJEJIIDwgMC4wNSAmIGFicyh0ZXRSLnJlc3BvbnNlJG1lYW5DIC0gdGV0Ui5yZXNwb25zZSRtZWFuRSk+MSldCnByaW50KHBhc3RlKCJUZXRSIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCIsbGVuZ3RoKHRldFIucmVzcG9uc2UuZGVncyksImdlbmVzIGluIHJlc3BvbnNlIHRvIHRldHJhY3ljbGluZSIsc2VwPSIgIikpCiNzYXZlIGZvbGQtY2hhbmdlIGZvciBhbGwgZ2VuZXMKdGV0Ui5yZXNwb25zZS5mb2xkLmNoYW5nZTwtdGV0Ui5yZXNwb25zZSRtZWFuRSAtIHRldFIucmVzcG9uc2UkbWVhbkMKbmFtZXModGV0Ui5yZXNwb25zZS5mb2xkLmNoYW5nZSk8LXJvd25hbWVzKHRldFIucmVzcG9uc2UpCiNkZWZpbmUgc2V0cyBvZiB1cC0gYW5kIGRvd24tcmVndWxhdGVkIGdlbmVzCnRldFIucmVzcG9uc2UuZGVncy51cDwtdGV0Ui5yZXNwb25zZS5kZWdzW3doaWNoKHRldFIucmVzcG9uc2UuZm9sZC5jaGFuZ2VbdGV0Ui5yZXNwb25zZS5kZWdzXT4wKV0KdGV0Ui5yZXNwb25zZS5kZWdzLmRvd248LXRldFIucmVzcG9uc2UuZGVnc1t3aGljaCh0ZXRSLnJlc3BvbnNlLmZvbGQuY2hhbmdlW3RldFIucmVzcG9uc2UuZGVnc108MCldCiN3cml0ZSBDU1YgZmlsZXMgd2l0aCB1cC0gYW5kIGRvd24tcmVndWxhdGVkIGdlbmVzIGZvciBkb3duc3RyZWFtIGFuYWx5c2lzIG9uIERBVklEIAojd3JpdGUuY3N2KGZpbGU9Ii4uL0RhdGEvRGlmZmVyZW50aWFsX2V4cHJlc3Npb25fYW5hbHlzaXMvREFWSURfZW5yaWNobWVudF9hbmFseXNpcy9JbnB1dC90ZXRSX3Jlc3BvbnNlX3VwXzA4MDgyMi5jc3YiLHRldFIucmVzcG9uc2UuZGVncy51cCxyb3cubmFtZXMgPSBGKQojd3JpdGUuY3N2KGZpbGU9Ii4uL0RhdGEvRGlmZmVyZW50aWFsX2V4cHJlc3Npb25fYW5hbHlzaXMvREFWSURfZW5yaWNobWVudF9hbmFseXNpcy9JbnB1dC90ZXRSX3Jlc3BvbnNlX2Rvd25fMDgwODIyLmNzdiIsdGV0Ui5yZXNwb25zZS5kZWdzLmRvd24scm93Lm5hbWVzID0gRikKI2NvdW50IFRGcywgZWZmbHV4IHB1bXBzLCBtZXRhYm9saWMgZ2VuZXMgYW5kIG90aGVyIGdlbmVzIGluIHRoZSB1cC0gYW5kIGRvd24tcmVndWxhdGVkIGdlbmVzCnVwLnRldFIucmVzcG9uc2UudmVjdG9yPC1jbGFzc2lmeS5kZWdzKHRldFIucmVzcG9uc2UuZGVncy51cCwiVVAiKQpkb3duLnRldFIucmVzcG9uc2UudmVjdG9yPC1jbGFzc2lmeS5kZWdzKHRldFIucmVzcG9uc2UuZGVncy5kb3duLCJET1dOIikKI2RpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2lzIGZvciBUZXRSKCtURVQpIHZzIFdUKCtURVQpCnRldFIud3QucmVzcG9uc2UuY29tcGFyaXNvbjwtYmF5ZXNUKGhhbmRlbC5ub3JtYWxpemVkLm1hdHJpeFssYyg0OjYsMTA6MTIpXSxudW1DID0gMyxudW1FID0gMyxjb25mID0gNyxkb011bHR0ZXN0ID0gVCkKdGV0Ui53dC5yZXNwb25zZS5jb21wYXJpc29uLmRlZ3M8LXJvd25hbWVzKHRldFIud3QucmVzcG9uc2UuY29tcGFyaXNvbilbd2hpY2godGV0Ui53dC5yZXNwb25zZS5jb21wYXJpc29uJEJIIDwgMC4wNSAmIGFicyh0ZXRSLnd0LnJlc3BvbnNlLmNvbXBhcmlzb24kbWVhbkMgLSB0ZXRSLnd0LnJlc3BvbnNlLmNvbXBhcmlzb24kbWVhbkUpPjEpXQpwcmludChwYXN0ZSgiVGV0UiAoK1RFVCkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIixsZW5ndGgodGV0Ui53dC5yZXNwb25zZS5jb21wYXJpc29uLmRlZ3MpLCJnZW5lcyB3aXRoIHJlc3BlY3QgdG8gV1QoK1RFVCkiLHNlcD0iICIpKQojc2F2ZSBmb2xkLWNoYW5nZSBmb3IgYWxsIGdlbmVzCnRldFIud3QucmVzcG9uc2UuY29tcGFyaXNvbi5mb2xkLmNoYW5nZTwtdGV0Ui53dC5yZXNwb25zZS5jb21wYXJpc29uJG1lYW5FIC0gdGV0Ui53dC5yZXNwb25zZS5jb21wYXJpc29uJG1lYW5DCm5hbWVzKHRldFIud3QucmVzcG9uc2UuY29tcGFyaXNvbi5mb2xkLmNoYW5nZSk8LXJvd25hbWVzKHRldFIud3QucmVzcG9uc2UuY29tcGFyaXNvbikKI2RlZmluZSBzZXRzIG9mIHVwLSBhbmQgZG93bi1yZWd1bGF0ZWQgZ2VuZXMKdGV0Ui53dC5yZXNwb25zZS5jb21wYXJpc29uLmRlZ3MudXA8LXRldFIud3QucmVzcG9uc2UuY29tcGFyaXNvbi5kZWdzW3doaWNoKHRldFIud3QucmVzcG9uc2UuY29tcGFyaXNvbi5mb2xkLmNoYW5nZVt0ZXRSLnd0LnJlc3BvbnNlLmNvbXBhcmlzb24uZGVnc10+MCldCnRldFIud3QucmVzcG9uc2UuY29tcGFyaXNvbi5kZWdzLmRvd248LXRldFIud3QucmVzcG9uc2UuY29tcGFyaXNvbi5kZWdzW3doaWNoKHRldFIud3QucmVzcG9uc2UuY29tcGFyaXNvbi5mb2xkLmNoYW5nZVt0ZXRSLnd0LnJlc3BvbnNlLmNvbXBhcmlzb24uZGVnc108MCldCiNjb3VudCBURnMsIGVmZmx1eCBwdW1wcywgbWV0YWJvbGljIGdlbmVzIGFuZCBvdGhlciBnZW5lcyBpbiB0aGUgdXAtIGFuZCBkb3duLXJlZ3VsYXRlZCBnZW5lcwp1cC50ZXRSLnd0LnJlc3BvbnNlLmNvbXBhcmlzb24udmVjdG9yPC1jbGFzc2lmeS5kZWdzKHRldFIud3QucmVzcG9uc2UuY29tcGFyaXNvbi5kZWdzLnVwLCJVUCIpCmRvd24udGV0Ui53dC5yZXNwb25zZS5jb21wYXJpc29uLnZlY3RvcjwtY2xhc3NpZnkuZGVncyh0ZXRSLnd0LnJlc3BvbnNlLmNvbXBhcmlzb24uZGVncy5kb3duLCJET1dOIikKI2NyZWF0ZSBGaWd1cmUgMUEKI3ZlY3RvciB0byBnZW5lcmF0ZSBibGFuayBzcGFjZQp6ZXJvLnZlY3RvcjwtcmVwKDAsNCkKI3NlbGVjdGVkIGNvbG9ycyBmb3IgYmFycGxvdApjb2xvcnMuYmFycGxvdDwtYygiZ3JleSIscmdiKDI1MywxNzQsOTcsbWF4Q29sb3JWYWx1ZSA9IDI1NSkscmdiKDE2NiwyMTcsMTA2LG1heENvbG9yVmFsdWUgPSAyNTUpLHJnYigyMTUsMjUsMjgsbWF4Q29sb3JWYWx1ZSA9IDI1NSkpCiNnZW5lcmF0ZSBiYXJwbG90CiNmaXJzdCwgaW5mb3JtYXRpb24gcmVnYXJkaW5nIHVwLXJlZ3VsYXRlZCBnZW5lcwpiYXJwbG90KHQocmJpbmQodXAud3QudmVjdG9yLHVwLnRldFIuYmFzYWwudmVjdG9yLHVwLnRldFIucmVzcG9uc2UudmVjdG9yLHVwLnRldFIud3QucmVzcG9uc2UuY29tcGFyaXNvbi52ZWN0b3IsemVyby52ZWN0b3IpKSxkZW5zaXR5PXJlcCgxNSw0KSAKICAgICAgICAsIGFuZ2xlPWMoMCw0NSw5MCwxMzUpICwgY29sPWNvbG9ycy5iYXJwbG90LHlsaW09YygtNTAwLDUwMCkseWxhYj0iTnVtYmVyIG9mIERFR3MiLG1haW49IkZpZy4gMUEiKQojdGhlbiwgYWRkIGluZm9ybWF0aW9uIHJlZ2FyZGluZyBkb3duLXJlZ3VsYXRlZCBnZW5lcyBpcyBhZGRlZApiYXJwbG90KHQocmJpbmQoZG93bi53dC52ZWN0b3IsZG93bi50ZXRSLmJhc2FsLnZlY3Rvcixkb3duLnRldFIucmVzcG9uc2UudmVjdG9yLGRvd24udGV0Ui53dC5yZXNwb25zZS5jb21wYXJpc29uLnZlY3Rvcix6ZXJvLnZlY3RvcikpLGRlbnNpdHk9cmVwKDE1LDQpICwgYW5nbGU9YygwLDQ1LDkwLDEzNSkgLGNvbD1jb2xvcnMuYmFycGxvdCxhZGQ9VCkKYWJsaW5lKGg9MCxjb2w9ImJsYWNrIixsd2Q9MikKYGBgCjEuMyBDcmVhdGUgRmlnLiBTMSAKYGBge3J9CiNGaWcuIFMxIChmb2xkLWNoYW5nZSBvZiB0cmFuc2NyaXB0IGxldmVsIG9mIGZlcm1lbnRhdGlvbi1yZWxhdGVkIGdlbmVzKQojbGlzdCBvZiBmZXJtZW50YXRpb24tcmVsYXRlZCBnZW5lcywgY29tcGlsZWQgZnJvbSBFY29DeWMgZGF0YWJhc2UKZmVybWVudGF0aW9uLmVjb2N5YzwtcmVhZC5jc3YoIi4uL0RhdGEvSW5wdXQvZmVybWVudGF0aW9uX3BhdGh3YXlfZWNvY3ljLmNzdiIsaGVhZGVyPUYpCiNmdW5jdGlvbiB0byB0cmFuc2xhdGUgZ2VuZSBuYW1lIHRvIGxvY3VzIHRhZwp0cmFuc2xhdGUuZ2VuZS5uYW1lLnRvLmxvY3VzPC1mdW5jdGlvbihnZW5lU2V0KQp7CiAgb3V0cHV0PC1jKCkKICBmb3IoZyBpbiBnZW5lU2V0KQogIHsKICBnZW5lLnBvczwtZ3JlcChwYXN0ZShnLCJfIixzZXA9IiIpLHJvd25hbWVzKHRyYW5zY3JpcHRpb25hbC5uZXR3b3JrKSkKICBpZihsZW5ndGgoZ2VuZS5wb3MpPT0xKQogIHsKICAgIG91dHB1dDwtYyhvdXRwdXQsc3Ryc3BsaXQocm93bmFtZXModHJhbnNjcmlwdGlvbmFsLm5ldHdvcmspW2dlbmUucG9zXSxzcGxpdD0iXyIpW1sxXV1bMl0pCiAgfQogIGVsc2UKICB7CiAgICBvdXRwdXQ8LWMob3V0cHV0LGcpCiAgfQogIH0KICBvdXRwdXQKfQojY29udmVydCBnZW5lIG5hbWVzIHRvIGxvY3VzIHRhZ3MKZmVybWVudGF0aW9uLmxvY2k8LXRyYW5zbGF0ZS5nZW5lLm5hbWUudG8ubG9jdXMoZmVybWVudGF0aW9uLmVjb2N5Y1ssMV0pCiNhZGQgbWlzc2luZyBsb2NpCmZlcm1lbnRhdGlvbi5sb2NpWzE1OjE2XTwtYygiYjE2NzUiLCJiMjkyOSIpCiNjcmVhdGUgbWF0cml4IHdpdGggYXZlcmFnZSBleHByZXNzaW9uIHZhbHVlIGZvciBXVCBhbmQgVGV0UiBzdHJhaW5zIGluIHRoZSBwcmVzZW5jZS9hYnNlbmNlIG9mIHRldHJhY3ljbGluZQpoYW5kZWwuYXZlcmFnZS5leHByZXNzaW9uPC1jYmluZChyb3dNZWFucyhoYW5kZWwubm9ybWFsaXplZC5tYXRyaXhbLDE6M10pLHJvd01lYW5zKGhhbmRlbC5ub3JtYWxpemVkLm1hdHJpeFssNDo2XSkscm93TWVhbnMoaGFuZGVsLm5vcm1hbGl6ZWQubWF0cml4Wyw3OjldKSxyb3dNZWFucyhoYW5kZWwubm9ybWFsaXplZC5tYXRyaXhbLDEwOjEyXSkpCiNkZWZpbmUgbWF0cml4IHdpdGggYXZlcmFnZSBleHByZXNzaW9uIHByb2ZpbGUgb2YgZmVybWVudGF0aW9uIGdlbmVzCmZlcm1lbnRhdGlvbi5wYXRod2F5LmF2ZXJhZ2UuZXhwcmVzc2lvbi5tYXRyaXg8LWhhbmRlbC5hdmVyYWdlLmV4cHJlc3Npb25bYXMudmVjdG9yKGZlcm1lbnRhdGlvbi5sb2NpKSxdCiNhZGQgZ2VuZSBuYW1lcyBpbmZvcm1hdGlvbiBhcyByb3duYW1lcwpyb3duYW1lcyhmZXJtZW50YXRpb24ucGF0aHdheS5hdmVyYWdlLmV4cHJlc3Npb24ubWF0cml4KTwtYXMudmVjdG9yKGZlcm1lbnRhdGlvbi5lY29jeWMkVjEpCiNhZGQgY29sdW1uIG5hbWVzCmNvbG5hbWVzKGZlcm1lbnRhdGlvbi5wYXRod2F5LmF2ZXJhZ2UuZXhwcmVzc2lvbi5tYXRyaXgpPC1jKCJXVCgtVEVUKSIsIldUKCtURVQpIiwgIlRldFIoLVRFVCkiLCAiVGV0UigrVEVUKSIpCiNjcmVhdGUgaGVhdG1hcCBkaXNwbGF5aW5nIGxvZzIgZm9sZC1jaGFuZ2Ugd2l0aCByZXNwZWN0IHRvIHVudHJlYXRlZCBXVAojaGVhdG1hcCBmb2xkLWNoYW5nZSBicmVha3MKaGVhdG1hcC5icmVha3M8LWMoLTMsLTIsLTEsLTAuNSwwLDAuNSwxLDIpCiNoZWF0bWFwIGNvbG9yIHBhbGV0dGUKaGVhdG1hcC5jb2xvcnM8LWNvbG9yUmFtcFBhbGV0dGUocmV2KGJyZXdlci5wYWwoNywgIlJkQnUiKSkgKSg4KVs4OjFdCnBoZWF0bWFwKGZlcm1lbnRhdGlvbi5wYXRod2F5LmF2ZXJhZ2UuZXhwcmVzc2lvbi5tYXRyaXhbLDI6NF0tZmVybWVudGF0aW9uLnBhdGh3YXkuYXZlcmFnZS5leHByZXNzaW9uLm1hdHJpeFssMV0sc2NhbGU9Im5vbmUiLGNvbG9yID1oZWF0bWFwLmNvbG9yc1stNV0sY2x1c3Rlcl9yb3dzPUYsY2x1c3Rlcl9jb2xzID0gRixmb250c2l6ZSA9IDgsYW5nbGVfY29sID0gOTAsCiAgICAgICAgIGJyZWFrcyA9IGhlYXRtYXAuYnJlYWtzLGxlZ2VuZF9icmVha3M9aGVhdG1hcC5icmVha3MsbGVnZW5kPVQsIG1haW49IkZpZy4gUzEiKQojZXZhbHVhdGUgc2lnbmlmaWNhbmNlIG9mIGZvbGQtY2hhbmdlIHVzaW5nIHJhbmRvbSBwZXJtdXRhdGlvbgojdG90YWwgcGVybXV0YXRpb25zCk49MTAwMDAKI2F2ZXJhZ2UgZm9sZCBjaGFuZ2Ugb2YgZmVybWVudGF0aW9uIGdlbmVzIGluIHRoZSBiYXNlbGluZSBjaGFuZ2UgaW4gVGV0Ugp0cnVlLmF2ZXJhZ2UuZm9sZC5jaGFuZ2UuZmVybWV0YXRpb248LW1lYW4oZmVybWVudGF0aW9uLnBhdGh3YXkuYXZlcmFnZS5leHByZXNzaW9uLm1hdHJpeFssM10tZmVybWVudGF0aW9uLnBhdGh3YXkuYXZlcmFnZS5leHByZXNzaW9uLm1hdHJpeFssMV0pCnJhbmRvbS5hdmVyYWdlLmZvbGQuY2hhbmdlPC1jKCkKZm9yKG4gaW4gMTpOKQp7CiAgcmFuZG9tLnNlbGVjdGVkLmdlbmVzPC1zYW1wbGUoMTpucm93KGhhbmRlbC5ub3JtYWxpemVkLm1hdHJpeCksbGVuZ3RoKGZlcm1lbnRhdGlvbi5sb2NpKSkKICByYW5kb20uZm9sZC5jaGFuZ2U8LWhhbmRlbC5hdmVyYWdlLmV4cHJlc3Npb25bcmFuZG9tLnNlbGVjdGVkLmdlbmVzLDNdLSBoYW5kZWwuYXZlcmFnZS5leHByZXNzaW9uW3JhbmRvbS5zZWxlY3RlZC5nZW5lcywxXQogIHJhbmRvbS5hdmVyYWdlLmZvbGQuY2hhbmdlPC1jKHJhbmRvbS5hdmVyYWdlLmZvbGQuY2hhbmdlLG1lYW4ocmFuZG9tLmZvbGQuY2hhbmdlKSkKfQojcGVybXV0YXRpb24gcC12YWx1ZQpwZXJtdXRhdGlvbi5wdmFsLmZlcm1lbnRhdGlvbi5nZW5lczwtbGVuZ3RoKHdoaWNoKGFicyhyYW5kb20uYXZlcmFnZS5mb2xkLmNoYW5nZSkgPj0gdHJ1ZS5hdmVyYWdlLmZvbGQuY2hhbmdlLmZlcm1ldGF0aW9uKSkvTgpwcmludChwYXN0ZSgiUGVybXV0YXRpb24gcC12YWx1ZSA9IixwZXJtdXRhdGlvbi5wdmFsLmZlcm1lbnRhdGlvbi5nZW5lcyksCiAgICAgIHNlcD0iIikKYGBgCjEuNCBDcmVhdGUgRmlnLiBTMiAoYWNyQSwgYWNyQiBhbmQgYWNyWiBleHByZXNzaW9uIGFuZCBmaXRuZXNzIHByb2ZpbGUgaW4gdGhlIHByZXNlbmNlIG9mIHRldHJhY3ljbGluZSkKYGBge3J9CiNlZmZsdXggcHVtcCBnZW5lcyBvZiBpbnRlcmVzdAphY3JBPC0iYjA0NjMiCmFjckI8LSJiMDQ2MiIKYWNyWjwtImIwNzYyIgojY3JlYXRlIEZpZy4gUzJBIC0gZXhwcmVzc2lvbiBwcm9maWxlcyBvZiBzZWxlY3RlZCBnZW5lcwpzZWxlY3RlZC5nZW5lcy5hdmVyYWdlLmV4cHJlc3Npb24ubWF0cml4PC1oYW5kZWwuYXZlcmFnZS5leHByZXNzaW9uW2MoYWNyQSxhY3JCLGFjclopLDI6NF0taGFuZGVsLmF2ZXJhZ2UuZXhwcmVzc2lvbltjKGFjckEsYWNyQixhY3JaKSwxXQpwYXIobWZyb3c9YygxLDEpKQpzZWxlY3RlZC5nZW5lcy5hdmVyYWdlLmV4cHJlc3Npb24ubWF0cml4PC1hcy5tYXRyaXgoc2VsZWN0ZWQuZ2VuZXMuYXZlcmFnZS5leHByZXNzaW9uLm1hdHJpeCkKI2FkZCBuYW1lcyBvZiBjb2x1bW5zCmNvbG5hbWVzKHNlbGVjdGVkLmdlbmVzLmF2ZXJhZ2UuZXhwcmVzc2lvbi5tYXRyaXgpPC1jKCJXVCgrKSIsIlRldFIoLSkiLCJUZXRSKCspIikKI2NyZWF0ZSBiYXJwbG90CmJhcnBsb3Qoc2VsZWN0ZWQuZ2VuZXMuYXZlcmFnZS5leHByZXNzaW9uLm1hdHJpeCxiZXNpZGU9VCxjb2w9YyhyZ2IoMTQxLDE2MCwyMDMsbWF4Q29sb3JWYWx1ZSA9IDI1NSkscmdiKDI1MiwxNDEsOTgsbWF4Q29sb3JWYWx1ZSA9IDI1NSkscmdiKDEwMiwxOTQsMTY1LG1heENvbG9yVmFsdWUgPSAyNTUpKSx5bGFiPSJMb2cyIGZvbGQtY2hhbmdlICh2cy4gV1QgY29udHJvbCkiLHlsaW09YygtMC41LDEuNSksbWFpbj0iRmlnLiBTMkEiKQogbGVnZW5kKCJ0b3BsZWZ0IixmaWxsPWMocmdiKDE0MSwxNjAsMjAzLG1heENvbG9yVmFsdWUgPSAyNTUpLHJnYigyNTIsMTQxLDk4LG1heENvbG9yVmFsdWUgPSAyNTUpLHJnYigxMDIsMTk0LDE2NSxtYXhDb2xvclZhbHVlID0gMjU1KSksbGVnZW5kID0gCiAgICAgICBjKCJBY3JBIiwiQWNyQiIsIkFjcloiKSkKI0ZpZy4gUzJCCiNsb2FkIGZpdG5lc3MgZGF0YSBmcm9tIE5pY2hvbHMgZXQgYWwuIChDZWxsIDIwMTEpCmZpdG5lc3Muc2NvcmVzPC1yZWFkLnhscygiLi4vRGF0YS9NaXNjZWxsYW5lb3VzX2ZpbGVzL3BoZW5vdGlwaWMgbGFuZHNjYXBlIHRhYmxlIHMyLnhscyIsaGVhZGVyPVQsZmlsbD1UKQojY3JlYXRlIGJveHBsb3QgZm9yIHNlbGVjdGVkIGdlbmVzIGluIHRldHJhY3ljbGluZSBjb25kaXRpb25zCnRldHJhY3ljbGluZS5jb25kaXRpb25zPC1ncmVwKCJURVRSQUNZQ0xJTkUiLGNvbG5hbWVzKGZpdG5lc3Muc2NvcmVzKSkKYm94cGxvdCh5bGltPWMoLTEyLDIpLHQoZml0bmVzcy5zY29yZXNbYygzOTY1LDEyNzgsMjgxOSksdGV0cmFjeWNsaW5lLmNvbmRpdGlvbnNdKSwKICAgICAgICBjb2w9YyhyZ2IoMTQxLDE2MCwyMDMsbWF4Q29sb3JWYWx1ZSA9IDI1NSkscmdiKDI1MiwxNDEsOTgsbWF4Q29sb3JWYWx1ZSA9IDI1NSkscmdiKDEwMiwxOTQsIDE2NSxtYXhDb2xvclZhbHVlID0gMjU1KSksb3V0bGluZT1ULGJveGx0eT0xLHdoaXNrbHR5ID0gMSwgc3RhcGxlbHR5ID0gMSwgbmFtZXM9YygiYWNyQSoiLCJhY3JCKiIsImFjcloiKSxmcmFtZT1GLHlsYWI9IkRlbGV0aW9uIGZpdG5lc3Mgc2NvcmUgaW4gdGV0cmFjeWNsaW5lIixjZXgubGFiPTEuMSxtYWluPSJGaWcuIFMyQiIpCmFibGluZShoPTAsbHR5PTIpCmBgYAoxLjUgQ3JlYXRlIEZpZy4gMUIgYW5kIGFjY29tcGFueWluZyBUYWJsZSBTMgpgYGB7cn0KI3BlcmZvcm0gZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gYW5hbHlzaXMgZm9yIFRldFIoK1RFVCkgdnMgV1QoLVRFVCkKdGV0Ui5wbHVzLnZzLldULm1pbnVzPC1iYXllc1QoaGFuZGVsLm5vcm1hbGl6ZWQubWF0cml4WyxjKDE6MywxMDoxMildLG51bUMgPSAzLG51bUUgPSAzLGNvbmYgPSA3LGRvTXVsdHRlc3QgPSBUKQojZGVmaW5lIERFR3MKdGV0Ui5wbHVzLnZzLldULm1pbnVzLmRlZ3M8LXJvd25hbWVzKHRldFIucGx1cy52cy5XVC5taW51cylbd2hpY2godGV0Ui5wbHVzLnZzLldULm1pbnVzJEJIIDwgMC4wNSAmIGFicyh0ZXRSLnBsdXMudnMuV1QubWludXMkbWVhbkMgLSB0ZXRSLnBsdXMudnMuV1QubWludXMkbWVhbkUpPjEpXQpwcmludChwYXN0ZSgiVGV0UigrVEVUKSBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQiLGxlbmd0aCh0ZXRSLnBsdXMudnMuV1QubWludXMuZGVncyksImdlbmVzIHdpdGggcmVzcGVjdCB0byBXVCgtVEVUKSIsc2VwPSIgIikpCiNkZWZpbmUgZm9sZC1jaGFuZ2UgdmVjdG9yCnRldFIucGx1cy52cy5XVC5taW51cy5mb2xkLmNoYW5nZTwtdGV0Ui5wbHVzLnZzLldULm1pbnVzJG1lYW5FIC0gdGV0Ui5wbHVzLnZzLldULm1pbnVzJG1lYW5DCm5hbWVzKHRldFIucGx1cy52cy5XVC5taW51cy5mb2xkLmNoYW5nZSk8LXJvd25hbWVzKHRldFIucGx1cy52cy5XVC5taW51cykKI2RlZmluZSB1cC0gYW5kIGRvd24tcmVndWxhdGVkIGdlbmVzCnRldFIucGx1cy52cy5XVC5taW51cy5kZWdzLnVwPC10ZXRSLnBsdXMudnMuV1QubWludXMuZGVnc1t3aGljaCh0ZXRSLnBsdXMudnMuV1QubWludXMuZm9sZC5jaGFuZ2VbdGV0Ui5wbHVzLnZzLldULm1pbnVzLmRlZ3NdPjApXQp0ZXRSLnBsdXMudnMuV1QubWludXMuZGVncy5kb3duPC10ZXRSLnBsdXMudnMuV1QubWludXMuZGVnc1t3aGljaCh0ZXRSLnBsdXMudnMuV1QubWludXMuZm9sZC5jaGFuZ2VbdGV0Ui5wbHVzLnZzLldULm1pbnVzLmRlZ3NdPDApXQojc2F2ZSBDU1YgZmlsZXMgd2l0aCB1cC0gYW5kIGRvd24tcmVndWxhdGVkIGdlbmVzIGZvciBkb3duc3RyZWFtIERBVklEIGFuYWx5c2lzCiN3cml0ZS5jc3YoZmlsZT0iLi4vRGF0YS9EaWZmZXJlbnRpYWxfZXhwcmVzc2lvbl9hbmFseXNpcy9EQVZJRF9lbnJpY2htZW50X2FuYWx5c2lzL0lucHV0L3RldFIrVEVUX1dULVRFVF91cHJlZ3VsYXRlZF8wODE1MjIuY3N2Iix0ZXRSLnBsdXMudnMuV1QubWludXMuZGVncy51cCxyb3cubmFtZXMgPSBGKQojd3JpdGUuY3N2KGZpbGU9Ii4uL0RhdGEvRGlmZmVyZW50aWFsX2V4cHJlc3Npb25fYW5hbHlzaXMvREFWSURfZW5yaWNobWVudF9hbmFseXNpcy9JbnB1dC90ZXRSK1RFVF9XVC1URVRfZG93bnJlZ3VsYXRlZF8wODE1MjIuY3N2Iix0ZXRSLnBsdXMudnMuV1QubWludXMuZGVncy5kb3duLHJvdy5uYW1lcyA9IEYpCiNGaWcuIDFCIC0gSGVhdG1hcCBmb3Igc2VsZWN0ZWQgZnVuY3Rpb25hbCB0ZXJtcwojcmVhZCBEQVZJRCBvdXRwdXQgZmlsZXMgKGkuZS4gZnVuY3Rpb25hbCBlbnJpY2htZW50KSBmb3IgV1QgcmVzcG9uc2UKI2NvbXBpbGUgc2V0IG9mIHRlcm1zIGFzc29jaWF0ZWQgd2l0aCBXVCByZXNwb25zZSAoZG93bi1yZWd1bGF0ZWQgZ2VuZXMpCmRhdmlkLnd0LnJlc3BvbnNlLmRvd248LXJlYWQuY3N2KCIuLi9EYXRhL0RpZmZlcmVudGlhbF9leHByZXNzaW9uX2FuYWx5c2lzL0RBVklEX2VucmljaG1lbnRfYW5hbHlzaXMvT3V0cHV0L0xhdGVzdF9vdXRwdXRfMjAyMi9kYXZpZF93dF9yZXNwb25zZV9kb3duLmNzdiIsaGVhZGVyPVQpCnNpZ25pZmljYW50LnRlcm1zLnd0LnJlc3BvbnNlLmRvd248LWFzLmNoYXJhY3RlcihkYXZpZC53dC5yZXNwb25zZS5kb3duJFRlcm1bd2hpY2goZGF2aWQud3QucmVzcG9uc2UuZG93biRCZW5qYW1pbmkgPCAwLjA1KV0pCiNzdGFydCB2ZWN0b3Igd2l0aCBhbGwgZW5yaWNoZWQgdGVybXMKYWxsLmVucmljaGVkLnRlcm1zPC1zaWduaWZpY2FudC50ZXJtcy53dC5yZXNwb25zZS5kb3duCiNjb21waWxlIHNldCBvZiB0ZXJtcyBhc3NvY2lhdGVkIHdpdGggdXAtcmVndWxhdGVkIGdlbmVzIGFzIHBhcnQgb2YgdGhlIFdUIHJlc3BvbnNlCmRhdmlkLnd0LnJlc3BvbnNlLnVwPC1yZWFkLmNzdigiLi4vRGF0YS9EaWZmZXJlbnRpYWxfZXhwcmVzc2lvbl9hbmFseXNpcy9EQVZJRF9lbnJpY2htZW50X2FuYWx5c2lzL091dHB1dC9MYXRlc3Rfb3V0cHV0XzIwMjIvZGF2aWRfd3RfcmVzcG9uc2VfdXAuY3N2IixoZWFkZXI9VCkKc2lnbmlmaWNhbnQudGVybXMud3QucmVzcG9uc2UudXA8LWFzLmNoYXJhY3RlcihkYXZpZC53dC5yZXNwb25zZS51cCRUZXJtW3doaWNoKGRhdmlkLnd0LnJlc3BvbnNlLnVwJEJlbmphbWluaSA8IDAuMDUpXSkKI2FkZCBlbnJpY2hlZCB0ZXJtcyB0byB2ZWN0b3Igd2l0aCBhbGwgb3Zlci1yZXByZXNlbnRlZCB0ZXJtcwphbGwuZW5yaWNoZWQudGVybXM8LXVuaW9uKGFsbC5lbnJpY2hlZC50ZXJtcyxzaWduaWZpY2FudC50ZXJtcy53dC5yZXNwb25zZS51cCkKI3JlYWQgREFWSUQgb3V0cHV0IChpLmUuIGZ1bmN0aW9uYWwgZW5yaWNobWVudCkgZm9yIFRldFIgYmFzYWxpbmUgY2hhbmdlcwojZGVmaW5lIHNldCBvZiB0ZXJtcyBhc3NvY2lhdGVkIHdpdGggVGV0UiBiYXNhbCByZXNwb25zZSAoZG93bi1yZWd1bGF0ZWQgZ2VuZXMpIApkYXZpZC50ZXRSLmJhc2FsLmRvd248LXJlYWQuY3N2KCIuLi9EYXRhL0RpZmZlcmVudGlhbF9leHByZXNzaW9uX2FuYWx5c2lzL0RBVklEX2VucmljaG1lbnRfYW5hbHlzaXMvT3V0cHV0L0xhdGVzdF9vdXRwdXRfMjAyMi9kYXZpZF90ZXRSX2Jhc2FsX2Rvd24uY3N2IixoZWFkZXI9VCkKc2lnbmlmaWNhbnQudGVybXMudGV0Ui5iYXNhbC5kb3duPC1hcy5jaGFyYWN0ZXIoZGF2aWQudGV0Ui5iYXNhbC5kb3duJFRlcm1bd2hpY2goZGF2aWQudGV0Ui5iYXNhbC5kb3duJEJlbmphbWluaSA8IDAuMDUpXSkKI2FkZCBlbnJpY2hlZCB0ZXJtcyB0byB2ZWN0b3Igd2l0aCBhbGwgb3Zlci1yZXByZXNlbnRlZCB0ZXJtcwphbGwuZW5yaWNoZWQudGVybXM8LXVuaW9uKGFsbC5lbnJpY2hlZC50ZXJtcyxzaWduaWZpY2FudC50ZXJtcy50ZXRSLmJhc2FsLmRvd24pCiNkZWZpbmUgc2V0IG9mIHRlcm1zIGFzc29jaWF0ZWQgd2l0aCB1cC1yZWd1bGF0ZWQgZ2VuZXMgYXMgcGFydCBvZiB0aGUgVGV0UiBiYXNhbCByZXNwb25zZQpkYXZpZC50ZXRSLmJhc2FsLnVwPC1yZWFkLmNzdigiLi4vRGF0YS9EaWZmZXJlbnRpYWxfZXhwcmVzc2lvbl9hbmFseXNpcy9EQVZJRF9lbnJpY2htZW50X2FuYWx5c2lzL091dHB1dC9MYXRlc3Rfb3V0cHV0XzIwMjIvZGF2aWRfdGV0Ul9iYXNhbF91cC5jc3YiLGhlYWRlcj1UKQpzaWduaWZpY2FudC50ZXJtcy50ZXRSLmJhc2FsLnVwPC1hcy5jaGFyYWN0ZXIoZGF2aWQudGV0Ui5iYXNhbC51cCRUZXJtW3doaWNoKGRhdmlkLnRldFIuYmFzYWwudXAkQmVuamFtaW5pIDwgMC4wNSldKQojYWRkIGVucmljaGVkIHRlcm1zIHRvIHZlY3RvciB3aXRoIGFsbCBvdmVyLXJlcHJlc2VudGVkIHRlcm1zCmFsbC5lbnJpY2hlZC50ZXJtczwtdW5pb24oYWxsLmVucmljaGVkLnRlcm1zLHNpZ25pZmljYW50LnRlcm1zLnRldFIuYmFzYWwudXApCiNyZWFkIERBVklEIG91dHB1dCAoaS5lLiBmdW5jdGlvbmFsIGVucmljaG1lbnQpIGZvciBUZXRSKCtURVQpIHZzIFdUKC1URVQpIAojZGVmaW5lIHNldCBvZiB0ZXJtcyBhc3NvY2lhdGVkIHdpdGggZG93bi1yZWd1bGF0ZWQgZ2VuZXMKZGF2aWQudGV0Ui5yZXNwb25zZS5kb3duPC1yZWFkLmNzdigiLi4vRGF0YS9EaWZmZXJlbnRpYWxfZXhwcmVzc2lvbl9hbmFseXNpcy9EQVZJRF9lbnJpY2htZW50X2FuYWx5c2lzL091dHB1dC9MYXRlc3Rfb3V0cHV0XzIwMjIvZGF2aWRfdGV0Ul9wbHVzX3ZzX3d0X21pbnVzX2Rvd24uY3N2IixoZWFkZXI9VCkKc2lnbmlmaWNhbnQudGVybXMudGV0Ui5yZXNwb25zZS5kb3duPC1hcy5jaGFyYWN0ZXIoZGF2aWQudGV0Ui5yZXNwb25zZS5kb3duJFRlcm1bd2hpY2goZGF2aWQudGV0Ui5yZXNwb25zZS5kb3duJEJlbmphbWluaSA8IDAuMDUpXSkKI2FkZCBlbnJpY2hlZCB0ZXJtcyB0byB2ZWN0b3Igd2l0aCBhbGwgb3Zlci1yZXByZXNlbnRlZCB0ZXJtcwphbGwuZW5yaWNoZWQudGVybXM8LXVuaW9uKGFsbC5lbnJpY2hlZC50ZXJtcyxzaWduaWZpY2FudC50ZXJtcy50ZXRSLnJlc3BvbnNlLmRvd24pCiNkZWZpbmUgc2V0IG9mIHRlcm1zIGFzc29jaWF0ZWQgd2l0aCB1cC1yZWd1bGF0ZWQgZ2VuZXMKZGF2aWQudGV0Ui5yZXNwb25zZS51cDwtcmVhZC5jc3YoIi4uL0RhdGEvRGlmZmVyZW50aWFsX2V4cHJlc3Npb25fYW5hbHlzaXMvREFWSURfZW5yaWNobWVudF9hbmFseXNpcy9PdXRwdXQvTGF0ZXN0X291dHB1dF8yMDIyL2RhdmlkX3RldFJfcGx1c192c193dF9taW51c191cC5jc3YiLGhlYWRlcj1UKQpzaWduaWZpY2FudC50ZXJtcy50ZXRSLnJlc3BvbnNlLnVwPC1hcy5jaGFyYWN0ZXIoZGF2aWQudGV0Ui5yZXNwb25zZS51cCRUZXJtW3doaWNoKGRhdmlkLnRldFIucmVzcG9uc2UudXAkQmVuamFtaW5pIDwgMC4wNSldKQojYWRkIGVucmljaGVkIHRlcm1zIHRvIHZlY3RvciB3aXRoIGFsbCBvdmVyLXJlcHJlc2VudGVkIHRlcm1zCmFsbC5lbnJpY2hlZC50ZXJtczwtdW5pb24oYWxsLmVucmljaGVkLnRlcm1zLHNpZ25pZmljYW50LnRlcm1zLnRldFIucmVzcG9uc2UudXApCiNjcmVhdGUgbWF0cml4IHdpdGggaW5mb3JtYXRpb24gZm9yIGFsbCB0aHJlZSBjb21wYXJpc29ucyB3aXRoIHJlc3BlY3QgdG8gdGhlIHVudHJlYXRlZCBXVCBzdHJhaW4KZnVuY3Rpb25hbC5lbnJpY2htZW50Lm1hdHJpeDwtbWF0cml4KG5jb2w9Myxucm93PWxlbmd0aChhbGwuZW5yaWNoZWQudGVybXMpLGRpbW5hbWVzID0gbGlzdChhbGwuZW5yaWNoZWQudGVybXMsYygiV1QoKykiLCJUZXRSKC0pIiwiVGV0UigrKSIpKSwwKQojZmlsbCBvdXQgdGhlICBlbnJpY2htZW50IG1hdHJpeCAKI3VwLSBhbmQgZG93bi1yZWd1bGF0ZWQgZ2VuZXMgYXJlIGluZGljYXRlZCBhcyAxcyBhbmQgLTFzLCByZXNwZWN0aXZlbHkKI2ZpbGwgZmlyc3QgY29sdW1uOiBXVCgrKSB2cyBXVCgtKQpmdW5jdGlvbmFsLmVucmljaG1lbnQubWF0cml4W3NpZ25pZmljYW50LnRlcm1zLnd0LnJlc3BvbnNlLmRvd24sIldUKCspIl08LSAtMQpmdW5jdGlvbmFsLmVucmljaG1lbnQubWF0cml4W3NpZ25pZmljYW50LnRlcm1zLnd0LnJlc3BvbnNlLnVwLCJXVCgrKSJdPC0gMQojZmlsbCBzZWNvbmQgY29sdW1uOiBUZXRSKC0pIHZzIFdUKC0pIApmdW5jdGlvbmFsLmVucmljaG1lbnQubWF0cml4W3NpZ25pZmljYW50LnRlcm1zLnRldFIuYmFzYWwuZG93biwiVGV0UigtKSJdPC0gLTEKZnVuY3Rpb25hbC5lbnJpY2htZW50Lm1hdHJpeFtzaWduaWZpY2FudC50ZXJtcy50ZXRSLmJhc2FsLnVwLCJUZXRSKC0pIl08LSAxCiNmaWxsIHRoaXJkIGNvbHVtbjogVGV0UigrKSB2cyBXVCgtKQpmdW5jdGlvbmFsLmVucmljaG1lbnQubWF0cml4W3NpZ25pZmljYW50LnRlcm1zLnRldFIucmVzcG9uc2UuZG93biwiVGV0UigrKSJdPC0gLTEKZnVuY3Rpb25hbC5lbnJpY2htZW50Lm1hdHJpeFtzaWduaWZpY2FudC50ZXJtcy50ZXRSLnJlc3BvbnNlLnVwLCJUZXRSKCspIl08LSAxCiNjcmVhdGUgc3ViLW1hdHJpeCB3aXRoIHNlbGVjdGVkIGZ1bmN0aW9uYWwgdGVybXMgKGZvciBGaWcuIDFCKQojZnVuY3Rpb25hbCB0ZXJtcyB3ZXJlIG1hbnVhbGx5IHNlbGVjdGVkCm1hdHJpeC5zZWxlY3RlZC50ZXJtczwtZnVuY3Rpb25hbC5lbnJpY2htZW50Lm1hdHJpeFtjKDEsMTUsMTksMjYsMzEsMjMsMjUsMjgsMTcsMzksMzgsNzEsODEsNTEsNDEsNDgsNzUsNzcsNzQsNDksNTAsNjEsNTIsNTgsNzMsODIsODAsODQsODc6ODkpLF0KI0ZpZy4gMUIKcGhlYXRtYXAodChtYXRyaXguc2VsZWN0ZWQudGVybXMpLGNvbG9yID1ibHVlcmVkKDMpWzM6MV0sc2NhbGUgPSAibm9uZSIsY2x1c3Rlcl9yb3dzPUYsY2x1c3Rlcl9jb2xzID0gRiwKICAgICAgICAgZm9udHNpemUgPSA4LGFuZ2xlX2NvbCA9IDkwLG1haW49IkZpZy4gMUIiKQojY3JlYXRlIHRhYmxlIFMyCiNpbml0aWFsaXplIG1hdHJpeAp0YWJsZVMyLm1hdHJpeDwtbWF0cml4KG5jb2w9NSxucm93PWxlbmd0aChhbGwuZW5yaWNoZWQudGVybXMpLAogICAgICAgICAgICAgICAgICAgICAgICAgZGltbmFtZXMgPSBsaXN0KGFsbC5lbnJpY2hlZC50ZXJtcyxjKCJXVCgrKSIsIlRldFIoLSkiLCJUZXRSKCspIiwiVG90YWwgbnVtYmVyIG9mIGdlbmVzIGFzc29jaWF0ZWQgd2l0aCB0ZXJtIiwiUC12YWx1ZSIpKSwwKQojZmlsbCByZWxldmFudCBpbmZvcm1hdGlvbiBmb3Igb3Zlci1yZXByZXNlbnRlZCB0ZXJtcyBpbiBXVCByZXNwb25zZSAgCiNkb3duLXJlZ3VsYXRlZCB0ZXJtcyAKZm9yKHQgaW4gc2lnbmlmaWNhbnQudGVybXMud3QucmVzcG9uc2UuZG93bikKIHsKICAgdGVybS5wb3NpdGlvbjwtd2hpY2goZGF2aWQud3QucmVzcG9uc2UuZG93biRUZXJtID09IHQpCiAgICNmaWxsIHJvdyBpbmZvcm1hdGlvbgogICB0YWJsZVMyLm1hdHJpeFt0LGMoMSw0KV08LSBhcy5tYXRyaXgoZGF2aWQud3QucmVzcG9uc2UuZG93blt0ZXJtLnBvc2l0aW9uLGMoIkNvdW50IiwiUG9wLkhpdHMiKV0pCiAgICNhZGQgcC12YWx1ZSBpbmZvcm1hdGlvbgogICB0ZXJtLnB2YWw8LWRhdmlkLnd0LnJlc3BvbnNlLmRvd25bdGVybS5wb3NpdGlvbiwiQmVuamFtaW5pIl0KICAgaWYodGFibGVTMi5tYXRyaXhbdCw1XT09MCkKICAgewogICAgIHRhYmxlUzIubWF0cml4W3QsNV08LXRlcm0ucHZhbAogICB9CiAgIGVsc2UKICAgewogICAgIHRhYmxlUzIubWF0cml4W3QsNV08LXBhc3RlKHRhYmxlUzIubWF0cml4W3QsNV0sdGVybS5wdmFsLHNlcD0iOyIpCiAgICB9Cn0KI3NhbWUgcHJvY2VzcyBmb3IgdXAtcmVndWxhdGVkIHRlcm1zCmZvcih0IGluIHNpZ25pZmljYW50LnRlcm1zLnd0LnJlc3BvbnNlLnVwKQogewogICB0ZXJtLnBvc2l0aW9uPC13aGljaChkYXZpZC53dC5yZXNwb25zZS51cCRUZXJtID09IHQpCiAgICNmaWxsIHJvdyBpbmZvcm1hdGlvbgogICB0YWJsZVMyLm1hdHJpeFt0LGMoMSw0KV08LSBhcy5tYXRyaXgoZGF2aWQud3QucmVzcG9uc2UudXBbdGVybS5wb3NpdGlvbixjKCJDb3VudCIsIlBvcC5IaXRzIildKQogICAjYWRkIHAtdmFsdWUgaW5mb3JtYXRpb24KICAgdGVybS5wdmFsPC1kYXZpZC53dC5yZXNwb25zZS51cFt0ZXJtLnBvc2l0aW9uLCJCZW5qYW1pbmkiXQogICBpZih0YWJsZVMyLm1hdHJpeFt0LDVdPT0wKQogICB7CiAgICAgdGFibGVTMi5tYXRyaXhbdCw1XTwtdGVybS5wdmFsCiAgIH0KICAgZWxzZQogICB7CiAgICAgdGFibGVTMi5tYXRyaXhbdCw1XTwtcGFzdGUodGFibGVTMi5tYXRyaXhbdCw1XSx0ZXJtLnB2YWwsc2VwPSI7IikKICAgIH0KfQogI2ZpbGwgaW5mb3JtYXRpb24gZm9yIFRldFIgYmFzYWwgcmVzcG9uc2UgY29sdW1uIAogI2Rvd24tcmVndWxhdGVkIHRlcm1zICAKICBmb3IodCBpbiBzaWduaWZpY2FudC50ZXJtcy50ZXRSLmJhc2FsLmRvd24pCiB7CiAgIHRlcm0ucG9zaXRpb248LXdoaWNoKGRhdmlkLnRldFIuYmFzYWwuZG93biRUZXJtID09IHQpCiAgIHRhYmxlUzIubWF0cml4W3QsYygyLDQpXTwtIGFzLm1hdHJpeChkYXZpZC50ZXRSLmJhc2FsLmRvd25bdGVybS5wb3NpdGlvbixjKCJDb3VudCIsIlBvcC5IaXRzIildKQogICAjYWRkIHAtdmFsdWUgaW5mb3JtYXRpb24KICAgdGVybS5wdmFsPC1kYXZpZC50ZXRSLmJhc2FsLmRvd25bdGVybS5wb3NpdGlvbiwiQmVuamFtaW5pIl0KICAgaWYodGFibGVTMi5tYXRyaXhbdCw1XT09MCkKICAgewogICAgIHRhYmxlUzIubWF0cml4W3QsNV08LXRlcm0ucHZhbAogICB9CiAgIGVsc2UKICAgewogICAgIHRhYmxlUzIubWF0cml4W3QsNV08LXBhc3RlKHRhYmxlUzIubWF0cml4W3QsNV0sdGVybS5wdmFsLHNlcD0iOyIpCiAgIH0KICB9CiAjZm9yIHVwLXJlZ3VsYXRlZCB0ZXJtcwogZm9yKHQgaW4gc2lnbmlmaWNhbnQudGVybXMudGV0Ui5iYXNhbC51cCkKIHsKICAgdGVybS5wb3NpdGlvbjwtd2hpY2goZGF2aWQudGV0Ui5iYXNhbC51cCRUZXJtID09IHQpCiAgIHRhYmxlUzIubWF0cml4W3QsYygyLDQpXTwtIGFzLm1hdHJpeChkYXZpZC50ZXRSLmJhc2FsLnVwW3Rlcm0ucG9zaXRpb24sYygiQ291bnQiLCJQb3AuSGl0cyIpXSkKICAgI2FkZCBwLXZhbHVlIGluZm9ybWF0aW9uCiAgIHRlcm0ucHZhbDwtZGF2aWQudGV0Ui5iYXNhbC51cFt0ZXJtLnBvc2l0aW9uLCJCZW5qYW1pbmkiXQogICBpZih0YWJsZVMyLm1hdHJpeFt0LDVdPT0wKQogICB7CiAgICAgdGFibGVTMi5tYXRyaXhbdCw1XTwtdGVybS5wdmFsCiAgIH0KICAgZWxzZQogICB7CiAgICAgdGFibGVTMi5tYXRyaXhbdCw1XTwtcGFzdGUodGFibGVTMi5tYXRyaXhbdCw1XSx0ZXJtLnB2YWwsc2VwPSI7IikKICAgfQogfQogI2ZpbGwgcmVsZXZhbnQgaW5mb3JtYXRpb24gZm9yIFRldFIoK1RFVCkgdnMgV1QoLVRFVCkgCiAjZG93bi1yZWd1bGF0ZWQgdGVybXMgIAogZm9yKHQgaW4gc2lnbmlmaWNhbnQudGVybXMudGV0Ui5yZXNwb25zZS5kb3duKQogewogICB0ZXJtLnBvc2l0aW9uPC13aGljaChkYXZpZC50ZXRSLnJlc3BvbnNlLmRvd24kVGVybSA9PSB0KQogICB0YWJsZVMyLm1hdHJpeFt0LGMoMyw0KV08LSBhcy5tYXRyaXgoZGF2aWQudGV0Ui5yZXNwb25zZS5kb3duW3Rlcm0ucG9zaXRpb24sYygiQ291bnQiLCJQb3AuSGl0cyIpXSkKICAgI2FkZCBwLXZhbHVlIGluZm9ybWF0aW9uCiAgIHRlcm0ucHZhbDwtZGF2aWQudGV0Ui5yZXNwb25zZS5kb3duW3Rlcm0ucG9zaXRpb24sIkJlbmphbWluaSJdCiAgIGlmKHRhYmxlUzIubWF0cml4W3QsNV09PTApCiAgIHsKICAgICB0YWJsZVMyLm1hdHJpeFt0LDVdPC10ZXJtLnB2YWwKICAgfQogICBlbHNlCiAgIHsKICAgICB0YWJsZVMyLm1hdHJpeFt0LDVdPC1wYXN0ZSh0YWJsZVMyLm1hdHJpeFt0LDVdLHRlcm0ucHZhbCxzZXA9IjsiKQogICB9CiB9CiAjZm9yIHVwLXJlZ3VsYXRlZCB0ZXJtcyAgCiBmb3IodCBpbiBzaWduaWZpY2FudC50ZXJtcy50ZXRSLnJlc3BvbnNlLnVwKQogewogICB0ZXJtLnBvc2l0aW9uPC13aGljaChkYXZpZC50ZXRSLnJlc3BvbnNlLnVwJFRlcm0gPT0gdCkKICAgdGFibGVTMi5tYXRyaXhbdCxjKDMsNCldPC0gYXMubWF0cml4KGRhdmlkLnRldFIucmVzcG9uc2UudXBbdGVybS5wb3NpdGlvbixjKCJDb3VudCIsIlBvcC5IaXRzIildKQogICAjYWRkIHAtdmFsdWUgaW5mb3JtYXRpb24KICAgdGVybS5wdmFsPC1kYXZpZC50ZXRSLnJlc3BvbnNlLnVwW3Rlcm0ucG9zaXRpb24sIkJlbmphbWluaSJdCiAgIGlmKHRhYmxlUzIubWF0cml4W3QsNV09PTApCiAgIHsKICAgIHRhYmxlUzIubWF0cml4W3QsNV08LXRlcm0ucHZhbAogICB9CiAgIGVsc2UKICAgewogICAgIHRhYmxlUzIubWF0cml4W3QsNV08LXBhc3RlKHRhYmxlUzIubWF0cml4W3QsNV0sdGVybS5wdmFsLHNlcD0iOyIpCiAgIH0KIH0KcHJpbnQodGFibGVTMi5tYXRyaXgpCmBgYAoxLjUgRmlnLiAxQy1FeHByZXNzaW9uIHByb2ZpbGUgb2YgYWVyb2JpYyByZXNwaXJhdGlvbiByZWxhdGVkIGdlbmVzCmBgYHtyfQojcmVhZCBsaXN0IG9mIFRDQSwgZWxlY3Ryb24gdHJhbnNwb3J0IGNoYWluIGFuZCBBVFAgc3ludGhhc2UgZ2VuZXMKYWVyb2JpYy5yZXNwaXJhdGlvbi50YWJsZTwtcmVhZC5jc3YoIi4uL0RhdGEvSW5wdXQvYWVyb2JpY19yZXNwaXJhdGlvbl9nZW5lcy5jc3YiKQphZXJvYmljLnJlc3BpcmF0aW9uLmxvY2k8LWFlcm9iaWMucmVzcGlyYXRpb24udGFibGUkTG9jdXMKYWVyb2JpYy5yZXNwaXJhdGlvbi5hdmVyYWdlLmV4cHJlc3Npb248LWhhbmRlbC5hdmVyYWdlLmV4cHJlc3Npb25bYXMudmVjdG9yKGFlcm9iaWMucmVzcGlyYXRpb24ubG9jaSksXQpyb3duYW1lcyhhZXJvYmljLnJlc3BpcmF0aW9uLmF2ZXJhZ2UuZXhwcmVzc2lvbik8LWFlcm9iaWMucmVzcGlyYXRpb24udGFibGUkTmFtZQojZGVmaW5lIGhlYXRtYXAgYnJlYWtzCmhlYXRtYXAuYnJlYWtzPC1jKC00LC0yLC0xLDAsMC41LDEsMS41KQpwaGVhdG1hcChhZXJvYmljLnJlc3BpcmF0aW9uLmF2ZXJhZ2UuZXhwcmVzc2lvblssMjo0XS1hZXJvYmljLnJlc3BpcmF0aW9uLmF2ZXJhZ2UuZXhwcmVzc2lvblssMV0sc2NhbGU9Im5vbmUiLGNvbG9yID1jb2xvclJhbXBQYWxldHRlKHJldihicmV3ZXIucGFsKDYsICJSZEJ1IikpICkoNilbNjoxXSwKICAgICAgICAgY2x1c3Rlcl9yb3dzPUYsY2x1c3Rlcl9jb2xzID0gRixmb250c2l6ZSA9IDgsYW5nbGVfY29sID0gOTAsCiAgICAgICAgIGJyZWFrcyA9IGhlYXRtYXAuYnJlYWtzLGxlZ2VuZF9icmVha3M9aGVhdG1hcC5icmVha3MsbGVnZW5kPVQsIG1haW49IkZpZy4gMUMiKQpgYGAKMi4xIFRhYmxlIDEKYGBge3J9CiNmdW5jdGlvbiB0byBnZW5lcmF0ZSBpbnB1dCBmaWxlcyBmb3IgTmV0U3VyZ2VvbiBhbGdvcml0aG0gKEJyZW50IGV0IGFsLiBQTkFTIDIwMTYpCmNyZWF0ZS5uZXRTdXJnZW9uLmlucHV0PC1mdW5jdGlvbihpbnB1dC5uZXR3b3JrLGJheWVzaWFuLnR0ZXN0Lm91dHB1dCxuYW1lLm91dHB1dC5maWxlKQp7CiNjaGFuZ2UgZ2VuZSBuYW1lcyAoZm9yIGJvdGggcm93cyBhbmQgY29sdW1ucykgdG8gbG9jaSBpbiB0aGUgaW5wdXQgbmV0d29yawpyb3duYW1lcyhpbnB1dC5uZXR3b3JrKTwtc2FwcGx5KDE6bnJvdyhpbnB1dC5uZXR3b3JrKSxmdW5jdGlvbih4KXtzdHJzcGxpdChyb3duYW1lcyhpbnB1dC5uZXR3b3JrKVt4XSxzcGxpdD0iXyIpW1sxXV1bMl19KQpjb2xuYW1lcyhpbnB1dC5uZXR3b3JrKTwtc2FwcGx5KDE6bmNvbChpbnB1dC5uZXR3b3JrKSxmdW5jdGlvbih4KXtzdHJzcGxpdChjb2xuYW1lcyhpbnB1dC5uZXR3b3JrKVt4XSxzcGxpdD0iXyIpW1sxXV1bMl19KQojZGVmaW5lIGdlbmVzIHByZXNlbnQgaW4gYm90aCBkYXRhc2V0cyAoaS5lLiwgZXhwcmVzc2lvbiBtYXRyaXggYW5kIHRyYW5zY3JpcHRpb25hbCBuZXR3b3JrKQpnZW5lcy5wcmVzZW50LmluLmJvdGguZGF0YXNldHM8LWludGVyc2VjdChyb3duYW1lcyhiYXllc2lhbi50dGVzdC5vdXRwdXQpLHJvd25hbWVzKGlucHV0Lm5ldHdvcmspKQojZmlsdGVyIHRoZSB0cmFuc2NyaXB0aW9uYWwgbmV0d29yayBhY2NvcmRpbmdseQppbnB1dC5uZXR3b3JrPC1pbnB1dC5uZXR3b3JrW2dlbmVzLnByZXNlbnQuaW4uYm90aC5kYXRhc2V0cyxdCiNyZW1vdmUgZnJvbSB0aGUgVFJOIHRob3NlIFRGcyB3aXRoIGxlc3MgdGhhbiBmaXZlIHRhcmdldHMgCmlucHV0Lm5ldHdvcms8LWlucHV0Lm5ldHdvcmtbLC0xKndoaWNoKGNvbFN1bXMoYWJzKGlucHV0Lm5ldHdvcmspKTw1KV0KI2NyZWF0ZSBpbnB1dCBuZXR3b3JrIGZvciBOZXRTdXJnZW9uIAojdGhlIGZvcm1hdCBvZiB0aGUgaW5wdXQgbmV0d29yayBpcyBURnMgeCBHZW5lcwojc2F2ZSBpbnB1dCBmaWxlCndyaXRlLnRhYmxlKHQoaW5wdXQubmV0d29yayksY29sLm5hbWVzPUYscm93Lm5hbWVzPUYscXVvdGU9RixmaWxlPXBhc3RlKCIuLi9EYXRhL05ldHdvcmtfYW5hbHlzaXMvTmV0U3VyZ2Vvbi9JbnB1dC8iLG5hbWUub3V0cHV0LmZpbGUsIl8iLFN5cy5EYXRlKCksIi5tdHIiLHNlcD0iIikpCiNleHRyYWN0IHEtdmFsdWVzIGZyb20gQmF5ZXNpYW4gVC10ZXN0cwpxLnZhbHVlczwtYmF5ZXNpYW4udHRlc3Qub3V0cHV0W3Jvd25hbWVzKGlucHV0Lm5ldHdvcmspLCJCSCJdCiNyZXBsYWNlIHplcm9lcyB3aXRoIG1pbmltdW0gcS12YWx1ZSBhbW9uZyB0aGUgbm9uLXplcm8gdmFsdWVzIHRvIGF2b2lkIGluZmluaXR5IGR1cmluZyB0aGUgbG9nIGNvbnZlcnNpb24KcG9zaXRpb24uemVyby5xLnZhbHVlczwtd2hpY2gocS52YWx1ZXMgPT0wKQppZihsZW5ndGgocG9zaXRpb24uemVyby5xLnZhbHVlcyk+MCkKewogIHEudmFsdWVzW3Bvc2l0aW9uLnplcm8ucS52YWx1ZXNdPC1taW4ocS52YWx1ZXNbLTEqIHBvc2l0aW9uLnplcm8ucS52YWx1ZXNdKQp9CiNjb252ZXJ0IHEtdmFsdWVzIG9mIG5vdCBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZXMgdG8gMQpxLnZhbHVlc1t3aGljaChxLnZhbHVlcyA+IDAuMDUgfCBhYnMoYmF5ZXNpYW4udHRlc3Qub3V0cHV0W3Jvd25hbWVzKGlucHV0Lm5ldHdvcmspLCJtZWFuQyJdLWJheWVzaWFuLnR0ZXN0Lm91dHB1dFtyb3duYW1lcyhpbnB1dC5uZXR3b3JrKSwibWVhbkUiXSk8MSldPTEKI2VzdGltYXRlIHRoZSBzaWduIG9mIGZvbGQtY2hhbmdlIGZvciBlYWNoIGdlbmUKZm9sZC5jaGFuZ2Uuc2lnbjwtIHNpZ24oYmF5ZXNpYW4udHRlc3Qub3V0cHV0W3Jvd25hbWVzKGlucHV0Lm5ldHdvcmspLCAiZm9sZCJdKQojc2lnbiAtbG9nIHEtdmFsdWVzIGJhc2VkIG9uIGZvbGQgY2hhbmdlIGRpcmVjdGlvbgpERXZlY3RvcjwtIGZvbGQuY2hhbmdlLnNpZ24gKiAtbG9nMihxLnZhbHVlcykgCiNyZW1vdmUgYW55IE5BCkRFdmVjdG9yW3doaWNoKGlzLm5hKERFdmVjdG9yKSldPC0wCiNzYXZlIGlucHV0IGZpbGVzCndyaXRlLnRhYmxlKERFdmVjdG9yLHNlcD0iICIsY29sLm5hbWVzPUYscm93Lm5hbWVzPUYscXVvdGU9RixmaWxlPXBhc3RlKCIuLi9EYXRhL05ldHdvcmtfYW5hbHlzaXMvTmV0U3VyZ2Vvbi9JbnB1dC8iLG5hbWUub3V0cHV0LmZpbGUsIl8iLFN5cy5EYXRlKCksIi52ZWN0IixzZXA9IiIpKQpyZWd1bGF0b3JzPC1jb2xuYW1lcyhpbnB1dC5uZXR3b3JrKQp3cml0ZS50YWJsZShyZWd1bGF0b3JzLHNlcD0iICIsY29sLm5hbWVzPUYscm93Lm5hbWVzPUYscXVvdGU9RixmaWxlPXBhc3RlKCIuLi9EYXRhL05ldHdvcmtfYW5hbHlzaXMvTmV0U3VyZ2Vvbi9JbnB1dC8iLG5hbWUub3V0cHV0LmZpbGUsIl8iLFN5cy5EYXRlKCksIi50ZnMiLHNlcD0iIikpCnRhcmdldHM8LXJvd25hbWVzKGlucHV0Lm5ldHdvcmspCndyaXRlLnRhYmxlKHRhcmdldHMsc2VwPSIgIixjb2wubmFtZXM9Rixyb3cubmFtZXM9RixxdW90ZT1GLGZpbGU9cGFzdGUoIi4uL0RhdGEvTmV0d29ya19hbmFseXNpcy9OZXRTdXJnZW9uL0lucHV0LyIsbmFtZS5vdXRwdXQuZmlsZSwiXyIsU3lzLkRhdGUoKSwiLm9yZnMiLHNlcD0iIikpCn0KI2NyZWF0ZSBmaWxlcyBmb3IgV1QgcmVzcG9uc2UgdG8gdGV0cmFjeWNsaW5lCmNyZWF0ZS5uZXRTdXJnZW9uLmlucHV0KGlucHV0Lm5ldHdvcmsgPSB0cmFuc2NyaXB0aW9uYWwubmV0d29yayxiYXllc2lhbi50dGVzdC5vdXRwdXQgPSB3dC5yZXNwb25zZSxuYW1lLm91dHB1dC5maWxlID0gIldUX1RFVCIpCiNjcmVhdGUgZmlsZXMgZm9yIFRldFIgYXQgYmFzZWxpbmUKY3JlYXRlLm5ldFN1cmdlb24uaW5wdXQoaW5wdXQubmV0d29yayA9IHRyYW5zY3JpcHRpb25hbC5uZXR3b3JrLGJheWVzaWFuLnR0ZXN0Lm91dHB1dCA9IHRldFIuYmFzYWwsbmFtZS5vdXRwdXQuZmlsZSA9ICJUZXRSX2Jhc2FsIikKI2NyZWF0ZSBmaWxlcyBmb3IgVGV0UiByZXNwb25zZSB0byB0ZXRyYWN5Y2xpbmUKY3JlYXRlLm5ldFN1cmdlb24uaW5wdXQoaW5wdXQubmV0d29yayA9IHRyYW5zY3JpcHRpb25hbC5uZXR3b3JrLGJheWVzaWFuLnR0ZXN0Lm91dHB1dCA9IHRldFIucmVzcG9uc2UsbmFtZS5vdXRwdXQuZmlsZSA9ICJUZXRSX3Jlc3BvbnNlIikKI3JlYWQgY29tcGlsZWQgTmV0U3VyZ2VvbiBvdXRwdXQgdG8gY3JlYXRlIFRhYmxlIDEgKG9ubHkgdG9wIDE1IFRGcyBmb3IgZWFjaCBjb21wYXJpc29uIHdlcmUgY29uc2lkZXJlZCBhcyBkaWZmZXJlbnRpYWxseSBhY3RpdmUpCm5ldHN1cmdlb24ub3V0cHV0PC1yZWFkLmNzdigiLi4vRGF0YS9OZXR3b3JrX2FuYWx5c2lzL05ldFN1cmdlb24vT3V0cHV0L3RhYmxlMV9yYXdfY29tcGlsZWRfTmV0U3VyZ2Vvbl9vdXRwdXQuY3N2IixoZWFkZXI9VCkKI2luaXRpYWxpemUgdGFibGUgMS1hZGQgaW5mb3JtYXRpb24gYWJvdXQgcmVndWxvbiBzaXplCnRhYmxlMTwtYygpCnRyYW5zY3JpcHRpb25hbC5uZXR3b3JrLmxvY2kudGFnczwtdHJhbnNjcmlwdGlvbmFsLm5ldHdvcmsKI2NoYW5nZSByb3ctIGFuZCBjb2x1bW4gbmFtZXMKcm93bmFtZXModHJhbnNjcmlwdGlvbmFsLm5ldHdvcmsubG9jaS50YWdzKTwtc2FwcGx5KDE6bnJvdyh0cmFuc2NyaXB0aW9uYWwubmV0d29yay5sb2NpLnRhZ3MpLGZ1bmN0aW9uKHgpe3N0cnNwbGl0KHJvd25hbWVzKHRyYW5zY3JpcHRpb25hbC5uZXR3b3JrLmxvY2kudGFncylbeF0sc3BsaXQ9Il8iKVtbMV1dWzJdfSkKY29sbmFtZXModHJhbnNjcmlwdGlvbmFsLm5ldHdvcmsubG9jaS50YWdzKTwtc2FwcGx5KDE6bmNvbCh0cmFuc2NyaXB0aW9uYWwubmV0d29yay5sb2NpLnRhZ3MpLGZ1bmN0aW9uKHgpe3N0cnNwbGl0KGNvbG5hbWVzKHRyYW5zY3JpcHRpb25hbC5uZXR3b3JrLmxvY2kudGFncylbeF0sc3BsaXQ9Il8iKVtbMV1dWzJdfSkKdGVtcG9yYWwudGFibGU8LWMoKQpmb3IodGYgaW4gbmV0c3VyZ2Vvbi5vdXRwdXQkTG9jdXMudGFnKQp7CiAgI251bWJlciBvZiB0YXJnZXRzIG9mIGN1cnJlbnQgVEYKICByZWd1bG9uLnNpemU8LWxlbmd0aChpbnRlcnNlY3QobmFtZXMod2hpY2godHJhbnNjcmlwdGlvbmFsLm5ldHdvcmsubG9jaS50YWdzWyx0Zl0hPTApKSxyb3duYW1lcyhoYW5kZWwubm9ybWFsaXplZC5tYXRyaXgpKSkKICAjZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIHRhcmdldHMgdGhhdCBhcmUgcGFydCBvZiB0aGUgYmFzZWxpbmUgY2hhbmdlCiAgZGUudGFyZ2V0cy50ZXRSLmJhc2FsPC1sZW5ndGgoaW50ZXJzZWN0KG5hbWVzKHdoaWNoKHRyYW5zY3JpcHRpb25hbC5uZXR3b3JrLmxvY2kudGFnc1ssdGZdIT0wKSksdGV0Ui5iYXNhbC5kZWdzKSkKICAjZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIHRhcmdldHMgdGhhdCBhcmUgcGFydCBvZiBUZXRSIHJlc3BvbnNlIHRvIHRldHJhY3ljbGluZQogIGRlLnRhcmdldHMudGV0Ui5hZGFwdGl2ZTwtbGVuZ3RoKGludGVyc2VjdChuYW1lcyh3aGljaCh0cmFuc2NyaXB0aW9uYWwubmV0d29yay5sb2NpLnRhZ3NbLHRmXSE9MCkpLHRldFIucmVzcG9uc2UuZGVncykpCiAgI2FkZCBjb2xsZWN0ZWQgaW5mb3JtYXRpb24gdG8gdGFibGUKICB0ZW1wb3JhbC50YWJsZTwtcmJpbmQodGVtcG9yYWwudGFibGUsY2JpbmQocmVndWxvbi5zaXplICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsZGUudGFyZ2V0cy50ZXRSLmJhc2FsLGRlLnRhcmdldHMudGV0Ui5hZGFwdGl2ZSkpCn0KI2FkZCBjb2x1bW4gbmFtZXMKY29sbmFtZXModGVtcG9yYWwudGFibGUpPC1jKCJSZWd1bG9uIHNpemUiLCJUYXJnZXRzLWJhc2FsIiwiVGFyZ2V0cy1hZGFwdGl2ZSIpCiNjb21iaW5lIG5ldHN1cmdlb24gb3V0cHV0IHdpdGggdGVtcG9yYWwgdGFibGUKdGFibGUxPC1jYmluZChuZXRzdXJnZW9uLm91dHB1dFssLTEqMjo0XSx0ZW1wb3JhbC50YWJsZSkKI2FkZCBsb2NpIGluZm9ybWF0aW9uCnRhYmxlMTwtY2JpbmQoY29udmVydC5sb2N1cy50by5nZW5lLm5hbWUodGFibGUxWywiTG9jdXMudGFnIl0pLHRhYmxlMSkKY29sbmFtZXModGFibGUxKVsxXTwtIlRyYW5zY3JpcHRpb24gZmFjdG9yIgojcHJpbnQgVGFibGUgIyAxCnByaW50KHRhYmxlMVtvcmRlcih0YWJsZTFbLCJSZWd1bG9uIHNpemUiXSxkZWNyZWFzaW5nID0gVCksXSkKI2V2YWx1YXRlIGhvdyBtYW55IERFR3MgYXJlIGNvbnRyb2xsZWQgYnkgdGhlIDI1IFRGcwojYWxsIGdlbmVzIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBpbiB0aGUgVGV0UiBzdHJhaW4gYmFja2dyb3VuZCAoYmFzZWxpbmUgY29tYmluZWQgd2l0aCBhZGFwdGl2ZSByZXNwb25zZSkKdGV0Ui5ERUdzPC11bmlvbih0ZXRSLmJhc2FsLmRlZ3MsdGV0Ui5yZXNwb25zZS5kZWdzKQojY29tcGlsZSBnZW5lcyB0aGF0IGFyZSBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgYnkgVGV0UiBhbmQgYXJlIHJlZ3VsYXRlZCBieSB0aGUgMjUgVEZzIGluIE5ldFN1cmdlb24gb3V0cHV0CmdlbmVzLmFmZmVjdGVkLmJ5LnRldFIucGhlbm90eXBlPC1jKCkKZm9yKHRmIGluIHRhYmxlMVssIkxvY3VzLnRhZyJdKQp7CiAgI2RlZmluZSBtZW1iZXJzIG9mIGN1cnJlbnQgVEYgcmVndWxvbiB0aGF0IGFyZSBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgaW4gYmFzYWwgb3IgYWRhcHRpdmUgcmVzcG9uc2UKICBkZS50YXJnZXRzLnRldFI8LWludGVyc2VjdChuYW1lcyh3aGljaCh0cmFuc2NyaXB0aW9uYWwubmV0d29yay5sb2NpLnRhZ3NbLHRmXSE9MCkpLHRldFIuREVHcykKICAjYWRkIGdlbmVzIGludG8gY29tcGlsYXRpb24gc2V0CiAgZ2VuZXMuYWZmZWN0ZWQuYnkudGV0Ui5waGVub3R5cGU8LXVuaW9uKGdlbmVzLmFmZmVjdGVkLmJ5LnRldFIucGhlbm90eXBlLGRlLnRhcmdldHMudGV0UikKfQpwcmludChsZW5ndGgoZ2VuZXMuYWZmZWN0ZWQuYnkudGV0Ui5waGVub3R5cGUpKQojc2ltaWxhciBhbmFseXNpcyBidXQgY291bnRpbmcgREVHcyBjb250cm9sbGVkIGJ5IHRoZSAxNSBURnMgYXNzb2NpYXRlZCB3aXRoIFRldFIgcmVzcG9uc2UgdG8gdGV0cmFjeWNsaW5lIChpLmUuLCBhZGFwdGl2ZSBURnMpCiNkZWZpbmUgYWRhcHRpdmUgVEZzCmFkYXB0aXZlLnRmczwtdGFibGUxWy0xKih3aGljaCh0YWJsZTFbLCJSZXNwb25zZSJdPT0iQmFzYWwiKSksIkxvY3VzLnRhZyJdCiN2ZWN0b3Igd2l0aCBtZW1iZXJzIG9mIGFkYXB0aXZlIFRGcyB0aGF0IHdlcmUgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGJ5IFRldFIgaW4gcmVzcG9uc2UgdG8gdGV0cmFjeWNsaW5lCnRhcmdldC5nZW5lcy50ZXRSLnJlc3BvbnNlPC1jKCkKI3ZlY3RvciB3aXRoIGFsbCBtZW1iZXJzIG9mIGFkYXB0aXZlIFRGIHJlZ3Vsb25zCmFkYXB0aXZlLnRmcy50b3RhbC50YXJnZXRzPC1jKCkKZm9yKHRmIGluIGFkYXB0aXZlLnRmcykKewogICNkZWZpbmUgY3VycmVudCBURiByZWd1bG9uCiAgY3VycmVudC50Zi5yZWd1bG9uPC1uYW1lcyh3aGljaCh0cmFuc2NyaXB0aW9uYWwubmV0d29yay5sb2NpLnRhZ3NbLHRmXSE9MCkpCiAgI2RlZmluZSBtZW1iZXJzIG9mIGN1cnJlbnQgVEYgcmVndWxvbiB0aGF0IHdlcmUgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGFzIHBhcnQgVGV0UiBhZGFwdGl2ZSByZXNwb25zZQogIGRlLnRhcmdldHMuYWRhcHRpdmU8LWludGVyc2VjdChjdXJyZW50LnRmLnJlZ3Vsb24sdGV0Ui5yZXNwb25zZS5kZWdzKQogICNhZGQgZ2VuZXMgaW50byBjb3JyZXNwb25kaW5nIHNldHMKICB0YXJnZXQuZ2VuZXMudGV0Ui5yZXNwb25zZTwtdW5pb24odGFyZ2V0LmdlbmVzLnRldFIucmVzcG9uc2UsZGUudGFyZ2V0cy5hZGFwdGl2ZSkKICBhZGFwdGl2ZS50ZnMudG90YWwudGFyZ2V0czwtdW5pb24oYWRhcHRpdmUudGZzLnRvdGFsLnRhcmdldHMsaW50ZXJzZWN0KGN1cnJlbnQudGYucmVndWxvbixyb3duYW1lcyhoYW5kZWwubm9ybWFsaXplZC5tYXRyaXgpKSkKfQpwcmludChsZW5ndGgodGFyZ2V0LmdlbmVzLnRldFIucmVzcG9uc2UpKQojY29tcHV0ZSBoeXBlci1nZW9tZXRyaWMgdGVzdCBwLXZhbHVlCnBoeXBlcihsZW5ndGgodGFyZ2V0LmdlbmVzLnRldFIucmVzcG9uc2UpLTEsbGVuZ3RoKGFkYXB0aXZlLnRmcy50b3RhbC50YXJnZXRzKSxucm93KGhhbmRlbC5ub3JtYWxpemVkLm1hdHJpeCktbGVuZ3RoKGFkYXB0aXZlLnRmcy50b3RhbC50YXJnZXRzKSxsZW5ndGgodGV0Ui5yZXNwb25zZS5kZWdzKSxsb3dlci50YWlsID0gRikKYGBgCjIuMiBGaWcgMkE6IGludGVyYWN0aW9ucyBhbW9uZyBkaWZmZXJlbnRpYWxseSBhY3RpdmUgVEZzCmBgYHtyfQojaW5pdGlhbGl6ZSBURi1URiBuZXR3b3JrCnRmLnRmLm5ldHdvcms8LWMoKQojYWRkIFRGLVRGIGludGVyYWN0aW9ucyB0aGF0IGludm9sdmUgVEZzIGluY2x1ZGVkIGluIFRhYmxlIDEKZm9yKHRmIGluIDE6bnJvdyh0YWJsZTEpKQp7CiAgI2N1cnJlbnQgVEYKICB0Zi5sb2N1czwtYXMuY2hhcmFjdGVyKHRhYmxlMVt0ZiwiTG9jdXMudGFnIl0pCiAgdGYubmFtZTwtYXMuY2hhcmFjdGVyKHRhYmxlMVt0ZiwiVHJhbnNjcmlwdGlvbiBmYWN0b3IiXSkKICAjVEYgcmVndWxvbiAKICB0Zi5yZWd1bG9uPC1uYW1lcyh3aGljaCh0cmFuc2NyaXB0aW9uYWwubmV0d29yay5sb2NpLnRhZ3NbLHRmLmxvY3VzXSE9MCkpCiAgI3RhcmdldCBURnMgLSBleGNsdWRpbmcgYXV0b3JlZ3VsYXRpb24KICB0YXJnZXQudGZzPC1zZXRkaWZmKGludGVyc2VjdCh0Zi5yZWd1bG9uLGFzLmNoYXJhY3Rlcih0YWJsZTFbLCJMb2N1cy50YWciXSkpLHRmLmxvY3VzKQogICNhZGQgcmVsZXZhbnQgaW50ZXJhY3Rpb25zCiAgaWYobGVuZ3RoKHRhcmdldC50ZnMpID4gMCkKICB7CiAgICAjc2lnbiAoYWN0aXZhdGlvbiBvciByZXByZXNzaW9uKSBvZiBURi1URiBpbnRlcmFjdGlvbnMKICAgIGludGVyYWN0aW9uLnNpZ25zPC1zaWduKHRyYW5zY3JpcHRpb25hbC5uZXR3b3JrLmxvY2kudGFnc1thcy5jaGFyYWN0ZXIodGFyZ2V0LnRmcyksdGYubG9jdXNdKQogICAgI2V4cGFuZCB0aGUgVEYtVEYgbmV0d29yawogICAgdGYudGYubmV0d29yazwtcmJpbmQodGYudGYubmV0d29yayxjYmluZChyZXAodGYubmFtZSxsZW5ndGgodGFyZ2V0LnRmcykpLGNvbnZlcnQubG9jdXMudG8uZ2VuZS5uYW1lKHRhcmdldC50ZnMpLGludGVyYWN0aW9uLnNpZ25zKSkKICB9Cn0KI2FkZCBjb2x1bW4gbmFtZXMKY29sbmFtZXModGYudGYubmV0d29yayk8LWMoIlJlZ3VsYXRvciIsIlRhcmdldCIsIlNpZ24iKQojZXh0ZW5kIHRoZSBURi1URiBuZXR3b3JrIHRvIHRha2UgaW50byBhY2NvdW50IHN1YnNldCBvZiB0YXJnZXQgZ2VuZXMgdGhhdCB3ZXJlIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCAoREUpIGluIFRldFIgcmVzcG9uc2UKI2ZvY3VzZWQgb24gdGhlIDE1IFRGcyBhc3NvY2lhdGVkIHdpdGggVGV0UiBhZGFwdGl2ZSByZXNwb25zZSBhbmQgdGhlaXIgREUgdGFyZ2V0cwp0ZW1wb3JhbC5zdWJuZXR3b3JrLm1hdHJpeDwtdHJhbnNjcmlwdGlvbmFsLm5ldHdvcmsubG9jaS50YWdzW2FzLmNoYXJhY3Rlcih0YXJnZXQuZ2VuZXMudGV0Ui5yZXNwb25zZSksYWRhcHRpdmUudGZzXQojZGVmaW5lIHVuaXF1ZSBwcm9maWxlcyBpbiB0cmFuc2NyaXB0aW9uYWwgc3VibmV0d29yayAoaS5lLiwga2VlcGluZyBhIHNpbmdsZSByb3cgdG8gcmVwcmVzZW50IGFsbCBnZW5lcyB3aXRoIHRoZSBzYW1lIHJlZ3VsYXRvcnMgaW4gdGhlIHRlbXBvcmFsLnN1Ym5ldHdvcmsubWF0cml4KQp1bmlxdWUuZ2VuZS5wcm9maWxlczwtdW5pcXVlLm1hdHJpeCh0ZW1wb3JhbC5zdWJuZXR3b3JrLm1hdHJpeCkKI2dyb3VwcyBvZiBnZW5lcyB3aXRoIHNhbWUgcmVndWxhdG9ycwpnZW5lLmdyb3VwczwtbGlzdCgpCiNyZWd1bGF0b3JzIG9mIGVhY2ggZ2VuZSBncm91cAp0Zi5ncm91cHM8LWMoKQpmb3IgKHIgaW4gMTpucm93KHVuaXF1ZS5nZW5lLnByb2ZpbGVzKSkKewogIHRlbXBvcmFsLmdlbmUuZ3JvdXA8LWMoKQogIGN1cnJlbnQucHJvZmlsZTwtdW5pcXVlLmdlbmUucHJvZmlsZXNbcixdCiAgI2RlZmluZSB3aGljaCBnZW5lcyBpbiB0aGUgdGVtcG9yYWwuc3VibmV0d29yay5tYXRyaXggaGF2ZSB0aGUgc2FtZSBwcm9maWxlIChpLmUuLCBzYW1lIHJlZ3VsYXRvcnMpCiAgZm9yKGcgaW4gdGFyZ2V0LmdlbmVzLnRldFIucmVzcG9uc2UpCiAgewogICAgaWYoYXBwbHkodGVtcG9yYWwuc3VibmV0d29yay5tYXRyaXhbZyxdPT10KGN1cnJlbnQucHJvZmlsZSksMSxhbGwpKQogICAgewogICAgICB0ZW1wb3JhbC5nZW5lLmdyb3VwPC1jKHRlbXBvcmFsLmdlbmUuZ3JvdXAsZykKICAgIH0KICB9CiAgI29ubHkgc2F2ZSBncm91cHMgd2l0aCBtb3JlIHRoYW4gZml2ZSBnZW5lcwogIGlmKGxlbmd0aCh0ZW1wb3JhbC5nZW5lLmdyb3VwKT41KQogIHsKICAgIGdlbmUuZ3JvdXBzW1tsZW5ndGgoZ2VuZS5ncm91cHMpKzFdXTwtdGVtcG9yYWwuZ2VuZS5ncm91cAogICAgZ3JvdXAucmVndWxhdG9yczwtY29udmVydC5sb2N1cy50by5nZW5lLm5hbWUobmFtZXMod2hpY2goY3VycmVudC5wcm9maWxlIT0wKSkpCiAgICB0Zi5ncm91cHM8LXJiaW5kKHRmLmdyb3VwcyxjYmluZChncm91cC5yZWd1bGF0b3JzLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcChwYXN0ZSgiR3JvdXAiLGxlbmd0aChnZW5lLmdyb3Vwcyksc2VwPSIiKSxsZW5ndGgoZ3JvdXAucmVndWxhdG9ycykpLGxlbmd0aCh0ZW1wb3JhbC5nZW5lLmdyb3VwKSkpCiAgIHdyaXRlLmNzdihmaWxlPXBhc3RlKCIuLi9EYXRhL05ldHdvcmtfYW5hbHlzaXMvTmV0U3VyZ2Vvbi9PdXRwdXQvdGVtcG9yYWxfY29yZWd1bGF0ZWRfZ2VuZV9ncm91cHNfYWRhcHRpdmVfcmVzcG9uc2VfZyIsbGVuZ3RoKGdlbmUuZ3JvdXBzKSwiXyIsU3lzLkRhdGUoKSwiLmNzdiIsc2VwPSIiKSxnZW5lLmdyb3Vwc1tbbGVuZ3RoKGdlbmUuZ3JvdXBzKV1dKQogICAgfQp9CiNhZGQgY29sdW1uIG5hbWVzCmNvbG5hbWVzKHRmLmdyb3Vwcyk8LWMoIlJlZ3VsYXRvciIsIlRhcmdldCIsIiNudW1iZXIgb2YgZ2VuZXMiKQojbWVyZ2UgdGhlIGdlbmUgY2x1c3RlcnMgd2l0aCB0aGUgVEYtVEYgbmV0d29yawp0Zi50Zi5uZXR3b3JrLnVuc2lnbmVkPC1yYmluZCh0Zi50Zi5uZXR3b3JrWywxOjJdLHRmLmdyb3Vwc1ssMToyXSkKI3Bsb3QgcmVzdWx0aW5nIGdlbmUgbmV0d29yayAtIEZpZy4gMkEgZHJhZnQuIAojdGhlIFRGLVRGIG5ldHdvcmsgaW4gbWFudXNjcmlwdCB3YXMgdmlzdWFsaXplZCB3aXRoIEN5dG9zY2FwZQp0Zi50Zi5uZXR3b3JrLmlncmFwaC5mb3JtYXQ8LWdyYXBoX2Zyb21fZGF0YV9mcmFtZSh0Zi50Zi5uZXR3b3JrLnVuc2lnbmVkICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx1bmlvbih0Zi50Zi5uZXR3b3JrLnVuc2lnbmVkWywiUmVndWxhdG9yIl0sdGYudGYubmV0d29yay51bnNpZ25lZFssIlRhcmdldCJdKSwgZGlyZWN0ZWQgPSBUKQpzZWxlY3RlZC5uZXR3b3JrLmxheW91dCA8LSBsYXlvdXRfbmljZWx5KHRmLnRmLm5ldHdvcmsuaWdyYXBoLmZvcm1hdCkKcGxvdCh0Zi50Zi5uZXR3b3JrLmlncmFwaC5mb3JtYXQsbGF5b3V0ID0gc2VsZWN0ZWQubmV0d29yay5sYXlvdXQsIGVkZ2UuYXJyb3cuc2l6ZSA9MC4yLHZlcnRleC5sYWJlbC5jZXg9MC41LHZlcnRleC5zaXplPTEzLG1haW49IkZpZy4gMkEgKGRyYWZ0KSIpCiNjb21wbGVtZW50IE5ldHN1cmdlb24gcmVzdWx0cyB3aXRoIGFuYWx5c2lzIG9mIEUuIGNvbGkgRUdSSU4yIG1vZGVsIChCcm9va3MgZXQgYWwuIDIwMTQsIE1TQikKI3JlYWQgRUdSSU4yIGNvcmVtcyAoaW4gc2ltcGxpZmllZCB0ZXJtcywgYSBjb3JlbSBpcyBhIGdyb3VwIG9mIGNvLXJlZ3VsYXRlZCBnZW5lcykKZWNvbGkuY29yZW1zLnRhYmxlPC1yZWFkLmNzdigiLi4vRGF0YS9OZXR3b3JrX2FuYWx5c2lzL0VHUklOX21vZGVsL2Vjb2xpX2VncmluMl9jb3JlbXMuY3N2IikKI2RlZmluZSBFLiBjb2xpIGNvcmVtcwplY29saS5jb3JlbXM8LWxpc3QoKQojc2F2ZSBuYW1lcyBvZiBhbGwgZ2VuZXMgaW5jbHVkZWQgdGhlIEUuIGNvbGkgRUdSSU4gbW9kZWwKZWNvbGkuZWdyaW4yLmdlbmVzPC1jKCkKI3NhdmUgbnVtYmVyIG9mIGdlbmVzIGluIGVhY2ggY29yZW0KY29yZW1zLnNpemU8LWMoKQpmb3IocyBpbiAxOm5yb3coZWNvbGkuY29yZW1zLnRhYmxlKSkKewogIGN1cnJlbnQuY29yZW08LXN0cnNwbGl0KGFzLmNoYXJhY3RlcihlY29saS5jb3JlbXMudGFibGUkR2VuZXNbc10pLHNwbGl0PSI7IixmaXhlZCA9IFQpW1sxXV0KICBlY29saS5jb3JlbXNbW2xlbmd0aChlY29saS5jb3JlbXMpKzFdXTwtY3VycmVudC5jb3JlbQogIGNvcmVtcy5zaXplPC1jKGNvcmVtcy5zaXplLGxlbmd0aChjdXJyZW50LmNvcmVtKSkKICBlY29saS5lZ3JpbjIuZ2VuZXM8LXVuaW9uKGVjb2xpLmVncmluMi5nZW5lcyxjdXJyZW50LmNvcmVtKQp9CiNuYW1lIGNvcmVtcyBhcyBjMSwgYzIsIGV0Yy4KbmFtZXMoZWNvbGkuY29yZW1zKTwtcGFzdGUoImMiLDE6bGVuZ3RoKGVjb2xpLmNvcmVtcyksc2VwPSIiKQojZnVuY3Rpb24gdG8gaWRlbnRpZnkgY29yZW1zIGVucmljaGVkIHdpdGggYSBwYXJ0aWN1bGFyICh1c2VyLXNwZWNpZmllZCkgc2V0IG9mIGdlbmVzCmV2YWx1YXRlLmNvcmVtLmVucmljaG1lbnQ8LWZ1bmN0aW9uKGNvcmVtLnNldCxnZW5lLnNldCkKewogICNtYXRyaXggd2l0aCBwLXZhbHVlcwogIGNvcmVtLmVucmljaG1lbnQgPSBtYXRyaXgobnJvdz1sZW5ndGgoY29yZW0uc2V0KSxuY29sPTUpCiAgY29sbmFtZXMoY29yZW0uZW5yaWNobWVudCk8LWMoJ3EnLCdtJywnbicsJ2snLCdwX3ZhbHVlJykKICByb3duYW1lcyhjb3JlbS5lbnJpY2htZW50KTwtbmFtZXMoY29yZW0uc2V0KQogIGZvcih4IGluIDE6bGVuZ3RoKGNvcmVtLnNldCkpIHsKICAgIHEgPSBsZW5ndGgoaW50ZXJzZWN0KGNvcmVtLnNldFtbeF1dLGdlbmUuc2V0KSkKICAgIG0gPSBsZW5ndGgoY29yZW0uc2V0W1t4XV0pCiAgICBrID0gbGVuZ3RoKGludGVyc2VjdChnZW5lLnNldCx1bmlxdWUoZWNvbGkuZWdyaW4yLmdlbmVzKSkpCiAgICBuID0gbGVuZ3RoKGVjb2xpLmVncmluMi5nZW5lcyktbQogICAgcHZhbCA9IE5BCiAgICAjaWYgdGhlIGludGVyc2VjdCBpcyBiaWdnZXIgdGhhbiB6ZXJvCiAgICBpZihxID4gMCkgewogICAgICAjY29tcHV0ZSBoeXBlcmdlb21ldHJpYyB0ZXN0IHAtdmFsdWUKICAgICAgcHZhbCA9IHBoeXBlcihxLG0sbixrLGxvd2VyLnRhaWw9RikKICAgIH0KICAgICNhZGQgdmFsdWVzIHRvIG1hdHJpeAogICAgY29yZW0uZW5yaWNobWVudFt4LF0gPSBjKHEsbSxuLGsscHZhbCkKICB9CiAgI3BlcmZvcm0gbXVsdGlwbGUgaHlwb3RoZXNlcyB0ZXN0aW5nIGNvcnJlY3Rpb24KICBjb3JlbS5lbnJpY2htZW50ID0gY2JpbmQoY29yZW0uZW5yaWNobWVudCxwX3ZhbHVlLkJIPXAuYWRqdXN0KGNvcmVtLmVucmljaG1lbnRbLCdwX3ZhbHVlJ10sbWV0aG9kPSdCSCcsbj1ucm93KGNvcmVtLmVucmljaG1lbnQpKSkKICAjc2VsZWN0IGVucmljaGVkIGNvcmVtcyB3aXRoIHRlbiBvciBtb3JlIG1lbWJlcnMKICBmaW5hbC5lbnJpY2hlZC5jb3JlbXMgPSByb3duYW1lcyhjb3JlbS5lbnJpY2htZW50KVt3aGljaChjb3JlbS5lbnJpY2htZW50WywncF92YWx1ZS5CSCddPD0wLjA1ICYgY29yZW0uZW5yaWNobWVudFssJ20nXT4gOSldCiAgb3V0cHV0PC1jb3JlbS5lbnJpY2htZW50W2ZpbmFsLmVucmljaGVkLmNvcmVtcyxdCiAgb3V0cHV0Cn0KI2V2YWx1YXRlIGVucmljaG1lbnQgb2YgRUdSSU4gY29yZW1zIChhbHNvIGtub3duIGFzIG1vZHVsZXMpIHdpdGggREVHcyBvZiBUZXRSIGJhc2VsaW5lIGFuZCBhZGFwdGl2ZSByZXNwb25zZXMKbW9kdWxlcy5lbnJpY2hlZC53aXRoLnRldFIuYmFzZWxpbmU8LWV2YWx1YXRlLmNvcmVtLmVucmljaG1lbnQoZWNvbGkuY29yZW1zLCB0ZXRSLmJhc2FsLmRlZ3MpCm1vZHVsZXMuZW5yaWNoZWQud2l0aC50ZXRSLmFkYXB0aXZlPC1ldmFsdWF0ZS5jb3JlbS5lbnJpY2htZW50KGVjb2xpLmNvcmVtcywgdGV0Ui5yZXNwb25zZS5kZWdzKQojc2F2ZSBuYW1lcyBvZiBURiByZWd1bG9ucyBvdmVyLXJlcHJlc2VudGVkIGluIGNvcmVtcyBlbnJpY2hlZCB3aXRoIFRldFIgYmFzYWxpbmUgY2hhbmdlcwpjb3JlbXMuZW5yaWNoZWQud2l0aC50ZXRSLmJhc2FsLlRGLnJlZ3Vsb25zPC1jKCkKI3NhdmUgbmFtZXMgb2YgVEYgcmVndWxvbnMgb3Zlci1yZXByZXNlbnRlZCBpbiBjb3JlbXMgZW5yaWNoZWQgd2l0aCBUZXRSIGFkYXB0aXZlIHJlc3BvbnNlIApjb3JlbXMuZW5yaWNoZWQud2l0aC50ZXRSLmFkYXB0aXZlLlRGLnJlZ3Vsb25zPC1jKCkKI3NhdmUgZ2VuZXMgaW4gY29yZW1zIGVucmljaGVkIHdpdGggYm90aCBUZXRSIERFR3MgQU5EIHRhcmdldHMgb2YgTmV0U3VyZ2VvbiBwcmVkaWN0ZWQgVEZzCmNvcmVtcy5lbnJpY2hlZC53aXRoLnRmLnJlZ3Vsb25zLmFuZC5kZWdzPC1jKCkKI3NhdmUgSUQgb2YgY29yZW1zIGVucmljaGVkIHdpdGggYm90aCBnZW5lIHNldHMKc2lnbmlmaWNhbnQuY29yZW1zPC1jKCkKIy0xKmMoMiwzLDUsOCwxMSwxNiwxOSwyMCkKZm9yKHRmIGluIHRhYmxlMVssIkxvY3VzLnRhZyJdKQp7CiAgY3VycmVudC5yZWd1bG9uPC1uYW1lcyh3aGljaCh0cmFuc2NyaXB0aW9uYWwubmV0d29yay5sb2NpLnRhZ3NbLHRmXSE9MCkpCiAgI2lkZW50aWZ5IGNvcmVtcyBlbnJpY2hlZCB3aXRoIGN1cnJlbnQgVEYgcmVndWxvbgogIHRlbXBvcmFsLmVucmljaG1lbnQuaW5mb3JtYXRpb248LWV2YWx1YXRlLmNvcmVtLmVucmljaG1lbnQoZWNvbGkuY29yZW1zLCBjdXJyZW50LnJlZ3Vsb24pCiAgI2RlZmluZSBjb3JlbXMgZW5yaWNoZWQgd2l0aCBjdXJyZW50IFRGIHJlZ3Vsb24gYW5kIFRldFIgYmFzYWwgcmVzcG9uc2UKICBpbnRlcnNlY3QuY29yZW1zPC1pbnRlcnNlY3Qocm93bmFtZXMobW9kdWxlcy5lbnJpY2hlZC53aXRoLnRldFIuYmFzZWxpbmUpLHJvd25hbWVzKHRlbXBvcmFsLmVucmljaG1lbnQuaW5mb3JtYXRpb24pKQogICNpZiB0aGVyZSBpcyBvbmUgb3IgbW9yZSBjb3JlbXMgZW5yaWNoZWQgd2l0aCBib3RoIGdlbmUgc2V0cwogIGlmKGxlbmd0aChpbnRlcnNlY3QuY29yZW1zKT4wKQogIHsKICAgIGNvcmVtcy5lbnJpY2hlZC53aXRoLnRldFIuYmFzYWwuVEYucmVndWxvbnM8LWMoY29yZW1zLmVucmljaGVkLndpdGgudGV0Ui5iYXNhbC5URi5yZWd1bG9ucyx0ZikKICAgICNjb21waWxlIG1lbWJlcnMgb2YgdGhlIGNvcmVtcyBlbnJpY2hlZCB3aXRoIGJvdGggZ2VuZSBzZXRzCiAgICBmb3IoYyBpbiBpbnRlcnNlY3QuY29yZW1zKQogICAgewogICAgICBjb3JlbXMuZW5yaWNoZWQud2l0aC50Zi5yZWd1bG9ucy5hbmQuZGVnczwtdW5pb24oY29yZW1zLmVucmljaGVkLndpdGgudGYucmVndWxvbnMuYW5kLmRlZ3MsZWNvbGkuY29yZW1zW1tjXV0pCiAgICAgIHNpZ25pZmljYW50LmNvcmVtczwtdW5pb24oc2lnbmlmaWNhbnQuY29yZW1zLGMpCiAgICB9CiAgfQogICNyZXBlYXQgYW5hbHlzaXMgZm9yIFRldFIgYWRhcHRpdmUgcmVzcG9uc2UKICAjZGVmaW5lIGNvcmVtcyBlbnJpY2hlZCB3aXRoIGN1cnJlbnQgVEYgcmVndWxvbiBhbmQgVGV0UiBhZGFwdGl2ZSByZXNwb25zZQogIGludGVyc2VjdC5jb3JlbXM8LWludGVyc2VjdChyb3duYW1lcyhtb2R1bGVzLmVucmljaGVkLndpdGgudGV0Ui5hZGFwdGl2ZSkscm93bmFtZXModGVtcG9yYWwuZW5yaWNobWVudC5pbmZvcm1hdGlvbikpCiAgaWYobGVuZ3RoKGludGVyc2VjdC5jb3JlbXMpPjApCiAgewogICAgY29yZW1zLmVucmljaGVkLndpdGgudGV0Ui5hZGFwdGl2ZS5URi5yZWd1bG9uczwtYyhjb3JlbXMuZW5yaWNoZWQud2l0aC50ZXRSLmFkYXB0aXZlLlRGLnJlZ3Vsb25zLHRmKQogICAgZm9yKGMgaW4gaW50ZXJzZWN0LmNvcmVtcykKICAgIHsKICAgICAgY29yZW1zLmVucmljaGVkLndpdGgudGYucmVndWxvbnMuYW5kLmRlZ3M8LXVuaW9uKGNvcmVtcy5lbnJpY2hlZC53aXRoLnRmLnJlZ3Vsb25zLmFuZC5kZWdzLGVjb2xpLmNvcmVtc1tbY11dKQogICAgICBzaWduaWZpY2FudC5jb3JlbXM8LXVuaW9uKHNpZ25pZmljYW50LmNvcmVtcyxjKQogICAgfQogIH0KfQojZGVmaW5lIGZpbmFsIHNldCBvZiBURnMgaWRlbnRpZmllZCBieSBib3RoIE5ldFN1cmdlb24gYW5kIEVHUklOLWJhc2VkIGFuYWx5c2lzCnRmcy5kZXRlY3RlZC5ieS5lZ3Jpbi5hbmFseXNpczwtdW5pb24oY29yZW1zLmVucmljaGVkLndpdGgudGV0Ui5iYXNhbC5URi5yZWd1bG9ucyxjb3JlbXMuZW5yaWNoZWQud2l0aC50ZXRSLmFkYXB0aXZlLlRGLnJlZ3Vsb25zKQpwcmludChjb252ZXJ0LmxvY3VzLnRvLmdlbmUubmFtZSh0ZnMuZGV0ZWN0ZWQuYnkuZWdyaW4uYW5hbHlzaXMpKQojaWRlbnRpZnkgVEZzIHdpdGggZGlmZmVyZW50aWFsIHJlZ3VsYXRvcnkgYWN0aXZpdHkgKGFsdGVybmF0aXZlIGFwcHJvYWNoKQojd2UgZmlyc3QgZXN0aW1hdGUgVEYgYWN0aXZpdHkKZ2VuZXMucHJlc2VudC5pbi50cmFuc2NyaXB0aW9uYWwubmV0d29yay5hbmQuZXhwcmVzc2lvbi5tYXRyaXg8LWludGVyc2VjdChyb3duYW1lcyh0cmFuc2NyaXB0aW9uYWwubmV0d29yay5sb2NpLnRhZ3MpLHJvd25hbWVzKGhhbmRlbC5ub3JtYWxpemVkLm1hdHJpeCkpCmZpbmFsLnRybi5uZXR3b3JrPC10cmFuc2NyaXB0aW9uYWwubmV0d29yay5sb2NpLnRhZ3NbZ2VuZXMucHJlc2VudC5pbi50cmFuc2NyaXB0aW9uYWwubmV0d29yay5hbmQuZXhwcmVzc2lvbi5tYXRyaXgsXQojcmVtb3ZlIFRGcyB3aXRoIGxlc3MgdGhhbiBmaXZlIHRhcmdldCBnZW5lcwpmaW5hbC50cm4ubmV0d29yazwtZmluYWwudHJuLm5ldHdvcmtbLC0xICogd2hpY2goY29sU3VtcyhhYnMoZmluYWwudHJuLm5ldHdvcmspKTw1KV0KI2tlZXAgb25seSBzaGFyZWQgZ2VuZXMgaW4gdGhlIGV4cHJlc3Npb24gbWF0cml4CnRldHJhY3ljbGluZS5leHByZXNzaW9uLm1hdHJpeDwtYXMubWF0cml4KGhhbmRlbC5ub3JtYWxpemVkLm1hdHJpeFtnZW5lcy5wcmVzZW50LmluLnRyYW5zY3JpcHRpb25hbC5uZXR3b3JrLmFuZC5leHByZXNzaW9uLm1hdHJpeCxdKQojY29tcHV0ZSBwc2V1ZG9pbnZlcnNlIG9mIHRoZSB0cmFuc2NyaXB0aW9uYWwgbmV0d29yawpwc2V1ZG9pbnZlcnNlLm1hdHJpeCA8LSBwc2V1ZG9pbnZlcnNlKGZpbmFsLnRybi5uZXR3b3JrKQojY29tcHV0ZSBURiBhY3Rpdml0aWVzCmVzdGltYXRlZC50Zi5hY3Rpdml0aWVzIDwtIHBzZXVkb2ludmVyc2UubWF0cml4ICUqJSB0ZXRyYWN5Y2xpbmUuZXhwcmVzc2lvbi5tYXRyaXgKcm93bmFtZXMoZXN0aW1hdGVkLnRmLmFjdGl2aXRpZXMpPC0gY29sbmFtZXMoZmluYWwudHJuLm5ldHdvcmspCiNwZXJmb3JtIHQtdGVzdCB0byBjb21wYXJlIGVzdGltYXRlZCBURkFzIGFjcm9zcyBzdHJhaW5zL2NvbmRpdGlvbnMKI3ZlY3RvciB3aXRoIHAtdmFsdWVzCnRmYS5wdmFsczwtYygpCiN2ZWN0b3Igd2l0aCByZWd1bG9uIHNpemUKcmVndWxvbi5zaXplPC1jKCkKI3ZlY3RvciB3aXRoIHAtdmFsdWVzIGZvciBUZXRSIGJhc2FsIHJlc3BvbnNlOiBUZXRSKC1URVQpIHZzIFdUKC1URVQpCnB2YWx1ZXMuYWN0aXZpdHkudGV0Ui5iYXNhbGluZTwtYygpCiN2ZWN0b3Igd2l0aCBwLXZhbHVlcyBmb3IgVGV0UiBhZGFwdGl2ZSByZXNwb25zZTogVGV0UigrVEVUKSB2cyBUZXRSKC1URVQpCnB2YWx1ZXMuYWN0aXZpdHkudGV0Ui5hZGFwdGl2ZTwtYygpCmZvcihyIGluIDE6bnJvdyhlc3RpbWF0ZWQudGYuYWN0aXZpdGllcykpCnsKICAjcGVyZm9ybSB0LXRlc3RzCiAgdGVtcG9yYWwucHZhbHVlPC10LnRlc3QoZXN0aW1hdGVkLnRmLmFjdGl2aXRpZXNbciw3OjldLGVzdGltYXRlZC50Zi5hY3Rpdml0aWVzW3IsMTozXSkkcC52YWx1ZQogIHB2YWx1ZXMuYWN0aXZpdHkudGV0Ui5iYXNhbGluZTwtYyhwdmFsdWVzLmFjdGl2aXR5LnRldFIuYmFzYWxpbmUsdGVtcG9yYWwucHZhbHVlKQogIHRlbXBvcmFsLnB2YWx1ZTI8LXQudGVzdChlc3RpbWF0ZWQudGYuYWN0aXZpdGllc1tyLDc6OV0sZXN0aW1hdGVkLnRmLmFjdGl2aXRpZXNbciwxMDoxMl0pJHAudmFsdWUKICBwdmFsdWVzLmFjdGl2aXR5LnRldFIuYWRhcHRpdmU8LWMocHZhbHVlcy5hY3Rpdml0eS50ZXRSLmFkYXB0aXZlLHRlbXBvcmFsLnB2YWx1ZTIpCn0KI3BlcmZvcm0gbXVsdGlwbGUgaHlwb3RoZXNpcyBjb3JyZWN0aW9uCnR0ZXN0LmFjdGl2aXRpZXMubWF0cml4PC1jYmluZChlc3RpbWF0ZWQudGYuYWN0aXZpdGllcyxwdmFsdWVzLmFjdGl2aXR5LnRldFIuYmFzYWxpbmUscC5hZGp1c3QocHZhbHVlcy5hY3Rpdml0eS50ZXRSLmJhc2FsaW5lLG1ldGhvZCA9ICJCSCIpLHB2YWx1ZXMuYWN0aXZpdHkudGV0Ui5hZGFwdGl2ZSxwLmFkanVzdChwdmFsdWVzLmFjdGl2aXR5LnRldFIuYWRhcHRpdmUsbWV0aG9kID0gIkJIIikpCmNvbG5hbWVzKHR0ZXN0LmFjdGl2aXRpZXMubWF0cml4KVtjKDEzOjE2KV08LWMoInAudmFsdWUuYmFzZWxpbmUiLCJhZGoucC52YWx1ZS5iYXNlbGluZSIsInAudmFsdWUuYWRhcHRpdmUiLCJhZGoucC52YWx1ZS5hZGFwdGl2ZSIpCiNDaGVjayBjaGFuZ2UgaW4gYWN0aXZpdHkgb2YgdGhlIDI1IFRGcyBwcmV2aW91c2x5IGlkZW50aWZpZWQgYnkgTmV0U3VyZ2VvbgpwcmludChjYmluZChjb252ZXJ0LmxvY3VzLnRvLmdlbmUubmFtZSh0YWJsZTFbLCJMb2N1cy50YWciXSkscm91bmQodHRlc3QuYWN0aXZpdGllcy5tYXRyaXhbYXMuY2hhcmFjdGVyKHRhYmxlMVssIkxvY3VzLnRhZyJdKSwxMzoxNl0sZGlnaXRzPTQpKSkKYGBgCjIuMyBGaWcuIDJCIC0gRm9sZCBjaGFuZ2Ugb2Ygc2VsZWN0ZWQgVEYgcmVndWxvbnMKYGBge3J9CiNkZWZpbmUgbWF0cml4IHdpdGggKGF2ZXJhZ2UpIGZvbGQtY2hhbmdlIHZhbHVlcyB3aXRoIHJlc3BlY3QgdG8gdW50cmVhdGVkIFdUCmhhbmRlbC5mb2xkY2hhbmdlLm1hdHJpeDwtaGFuZGVsLmF2ZXJhZ2UuZXhwcmVzc2lvblssMjo0XS1oYW5kZWwuYXZlcmFnZS5leHByZXNzaW9uWywxXQojZnVuY3Rpb24gdG8gY29tcHV0ZSBzaWduaWZpY2FuY2Ugb2YgZm9sZC1jaGFuZ2Ugb2YgYSBnaXZlbiBzZXQgb2YgZ2VuZXMgdnMgcmFuZG9tIHNlbGVjdGlvbgogICAgcGVybXV0YXRpb24uZnVuY3Rpb248LWZ1bmN0aW9uKHRydWUuZ2VuZXMsY29sdW1uLm9mLmZvbGQuY2hhbmdlLm1hdHJpeCkKICAgIHsKICAgICAgI251bWJlciBvZiByYW5kb20gZ2VuZSBzYW1wbGluZwogICAgICBOPTEwMDAwCiAgICAgIHRydWUuYXZlcmFnZS5mb2xkLmNoYW5nZTwtbWVhbihoYW5kZWwuZm9sZGNoYW5nZS5tYXRyaXhbdHJ1ZS5nZW5lcyxjb2x1bW4ub2YuZm9sZC5jaGFuZ2UubWF0cml4XSkKICAgICAgcmFuZG9tLmNvbXBpbGF0aW9uPC1jKCkKICAgIGZvcihuIGluIDE6TikKICAgIHsKICAgICAgcmFuZG9tLmZvbGQuY2hhbmdlPC1oYW5kZWwuZm9sZGNoYW5nZS5tYXRyaXhbc2FtcGxlKDE6bnJvdyhoYW5kZWwuZm9sZGNoYW5nZS5tYXRyaXgpLGxlbmd0aCh0cnVlLmdlbmVzKSksY29sdW1uLm9mLmZvbGQuY2hhbmdlLm1hdHJpeF0KICAgICAgcmFuZG9tLmNvbXBpbGF0aW9uPC1jKHJhbmRvbS5jb21waWxhdGlvbixtZWFuKHJhbmRvbS5mb2xkLmNoYW5nZSkpCiAgICB9CiAgICAgICNjb25zZXJ2YXRpdmUgcC12YWx1ZSBlc3RpbWF0aW9uIChtaW5pbXVtIG9mIG9uZS10YWlsZWQgdnMgdHdvLXRhaWxlZCB0ZXN0KQogICAgICBlc3RpbWF0ZWQucHZhbHVlPC1taW4oYyhsZW5ndGgod2hpY2gocmFuZG9tLmNvbXBpbGF0aW9uID49IHRydWUuYXZlcmFnZS5mb2xkLmNoYW5nZSkpL04sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlbmd0aCh3aGljaChyYW5kb20uY29tcGlsYXRpb24gPD0gdHJ1ZS5hdmVyYWdlLmZvbGQuY2hhbmdlKSkvTiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVuZ3RoKHdoaWNoKGFicyhyYW5kb20uY29tcGlsYXRpb24pPj1hYnModHJ1ZS5hdmVyYWdlLmZvbGQuY2hhbmdlKSkpKSkKICAgICAgI3JldHVybiBlc3RpbWF0ZWQgcC12YWx1ZQogICAgICBlc3RpbWF0ZWQucHZhbHVlCiAgICB9CiNnZW5lcmF0ZSBib3hwbG90cyBmb3Igc2VsZWN0ZWQgVEZzIChwcmVkaWN0ZWQgYXMgZGlmZmVyZW50aWFsbHkgYWN0aXZlIGJhc2VkIG9uIG5ldHdvcmsgYW5hbHlzZXMgYWJvdmUpICAgIApzZWxlY3RlZC50ZnM8LWMoImFyY0EiLCJtYXJBIiwiZ2FkRSIpCmZvcih0Zi5uYW1lIGluIHNlbGVjdGVkLnRmcykKewogIHRmLmxvY3VzPC10cmFuc2xhdGUuZ2VuZS5uYW1lLnRvLmxvY3VzKHRmLm5hbWUpCiAgaWYodGYubmFtZT09ImFyY0EiKQogIHsKICAgI2ZvY3VzIG9uIEFyY0EgcmVwcmVzc2VkIGdlbmVzIAogICAjQXJjQSBpcyBtYWlubHkgYSByZXByZXNzb3I6IGl0IHJlcHJlc3NlcyA3My4yJSBvZiBpdHMgdGFyZ2V0cwogICAjZnVydGhlcm1vcmUsIDgwJSBvZiBBcmNBIERFIHRhcmdldCBnZW5lcyBhcmUgcmVwcmVzc2VkIGJ5IEFyY0EKICAgY3VycmVudC5yZWd1bG9uLnJlcHJlc3Npb248LW5hbWVzKHdoaWNoKGZpbmFsLnRybi5uZXR3b3JrWyx0Zi5sb2N1c108MCkpCiAgICNmb2N1cyBvbiBERUdzIChlaXRoZXIgaW4gdGhlIFRldFIgYmFzYWxpbmUgb3IgYWRhcHRpdmUgcmVzcG9uc2UpCiAgIGN1cnJlbnQucmVndWxvbi5yZXByZXNzaW9uPC1pbnRlcnNlY3QoY3VycmVudC5yZWd1bG9uLnJlcHJlc3Npb24sdGV0Ui5ERUdzKQogICAjZm9sZC1jaGFuZ2UgbWF0cml4IHdpdGggREUgdGFyZ2V0IGdlbmVzCiAgIHRlbXBvcmFsLmZvbGQuY2hhbmdlLm1hdHJpeDwtcmJpbmQoY2JpbmQoaGFuZGVsLmZvbGRjaGFuZ2UubWF0cml4W2N1cnJlbnQucmVndWxvbi5yZXByZXNzaW9uLDFdLHJlcCgiV1QoKykiLGxlbmd0aChjdXJyZW50LnJlZ3Vsb24ucmVwcmVzc2lvbikpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgY2JpbmQoaGFuZGVsLmZvbGRjaGFuZ2UubWF0cml4W2N1cnJlbnQucmVndWxvbi5yZXByZXNzaW9uLDJdLHJlcCgiVGV0UigtKSIsbGVuZ3RoKGN1cnJlbnQucmVndWxvbi5yZXByZXNzaW9uKSkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICBjYmluZChoYW5kZWwuZm9sZGNoYW5nZS5tYXRyaXhbY3VycmVudC5yZWd1bG9uLnJlcHJlc3Npb24sM10scmVwKCJUZXRSKCspIixsZW5ndGgoY3VycmVudC5yZWd1bG9uLnJlcHJlc3Npb24pKSkpCiAgICB0ZW1wb3JhbC5mb2xkLmNoYW5nZS5tYXRyaXg8LWFzLmRhdGEuZnJhbWUodGVtcG9yYWwuZm9sZC5jaGFuZ2UubWF0cml4KQogICAgI2RlZmluZSBjb2x1bW4gbmFtZXMKICAgIGNvbG5hbWVzKHRlbXBvcmFsLmZvbGQuY2hhbmdlLm1hdHJpeCk8LWMoIkV4cHJlc3Npb24iLCJTdHJhaW4iKQogICAgdGVtcG9yYWwuZm9sZC5jaGFuZ2UubWF0cml4JEV4cHJlc3Npb248LWFzLm51bWVyaWMoYXMudmVjdG9yKHRlbXBvcmFsLmZvbGQuY2hhbmdlLm1hdHJpeCRFeHByZXNzaW9uKSkKICAgIHRlbXBvcmFsLmZvbGQuY2hhbmdlLm1hdHJpeCRTdHJhaW48LWZhY3Rvcih0ZW1wb3JhbC5mb2xkLmNoYW5nZS5tYXRyaXgkU3RyYWluLGxldmVscyA9IGMoIldUKCspIiwiVGV0UigtKSIsIlRldFIoKykiKSxvcmRlcmVkID0gVFJVRSkKICAgICNjcmVhdGUgYmFycGxvdCB3aXRoIGdncGxvdAogICAgYmFycGxvdC5hcmNBIDwtIGdncGxvdCh0ZW1wb3JhbC5mb2xkLmNoYW5nZS5tYXRyaXgsIGFlcyh4PVN0cmFpbiwgeT1FeHByZXNzaW9uLGZpbGw9U3RyYWluKSkgKyAKICAgICAgZ2VvbV9ib3hwbG90KGNvbG9yPSJyZWQiKSsgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTI0KSkKICAgIHByaW50KGJhcnBsb3QuYXJjQStzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9cmVwKCJ3aGl0ZSIsMykpICsgCiAgICBnZ3RpdGxlKHBhc3RlKHRmLm5hbWUsIi0tfCIsbGVuZ3RoKGN1cnJlbnQucmVndWxvbi5yZXByZXNzaW9uKSwiZ2VuZXMiLHNlcD0iICIpKSkKICAgICNydW4gcmFuZG9tIHBlcm11dGF0aW9uIHRlc3QgZm9yIGVhY2ggY29tcGFyaXNvbiAoZS5nLiwgV1QrVEVUIHZzIFdULVRFVCwgVGV0Ui1URVQgdnMgV1QtVEVULCBldGMuKQogICAgcHJpbnQocGFzdGUodGYubmFtZSwiLVdUK1RFVCB2cyBXVC1URVQ6IixwZXJtdXRhdGlvbi5mdW5jdGlvbihjdXJyZW50LnJlZ3Vsb24ucmVwcmVzc2lvbiwxKSxzZXA9IiIpKQogICAgcHJpbnQocGFzdGUodGYubmFtZSwiLVRldFItVEVUIHZzIFdULVRFVDoiLHBlcm11dGF0aW9uLmZ1bmN0aW9uKGN1cnJlbnQucmVndWxvbi5yZXByZXNzaW9uLDIpLHNlcD0iIikpCiAgICBwcmludChwYXN0ZSh0Zi5uYW1lLCItVGV0UitURVQgdnMgV1QtVEVUOiIscGVybXV0YXRpb24uZnVuY3Rpb24oY3VycmVudC5yZWd1bG9uLnJlcHJlc3Npb24sMyksc2VwPSIiKSkKICB9CiAgI2lmIFRGIGlzIE1hckEgb3IgR2FkRQogICNib3RoIE1hckEgYW5kIEdhZEUgbWFpbmx5IGFjdCBhcyBhY3RpdmF0b3JzIChpLmUuLCBwb3NpdGl2ZWx5IHJlZ3VsYXRlID43OSUgb2YgdGhlaXIgdGFyZ2V0IGdlbmVzKQogIGVsc2UKICB7CiAgY3VycmVudC5yZWd1bG9uLmFjdGl2YXRpb248LW5hbWVzKHdoaWNoKGZpbmFsLnRybi5uZXR3b3JrWyx0Zi5sb2N1c10+MCkpCiAgaWYobGVuZ3RoKGN1cnJlbnQucmVndWxvbi5hY3RpdmF0aW9uKT4wKQogICAgewogICAjZm9jdXMgb24gREVHcyAoZWl0aGVyIGluIHRoZSBUZXRSIGJhc2FsaW5lIG9yIGFkYXB0aXZlIHJlc3BvbnNlKQogICBjdXJyZW50LnJlZ3Vsb24uYWN0aXZhdGlvbjwtaW50ZXJzZWN0KGN1cnJlbnQucmVndWxvbi5hY3RpdmF0aW9uLHRldFIuREVHcykKICAgI2ZvbGQtY2hhbmdlIG1hdHJpeCB3aXRoIERFIHRhcmdldCBnZW5lcwogICB0ZW1wb3JhbC5mb2xkLmNoYW5nZS5tYXRyaXg8LXJiaW5kKGNiaW5kKGhhbmRlbC5mb2xkY2hhbmdlLm1hdHJpeFtjdXJyZW50LnJlZ3Vsb24uYWN0aXZhdGlvbiwxXSxyZXAoIldUKCspIixsZW5ndGgoY3VycmVudC5yZWd1bG9uLmFjdGl2YXRpb24pKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNiaW5kKGhhbmRlbC5mb2xkY2hhbmdlLm1hdHJpeFtjdXJyZW50LnJlZ3Vsb24uYWN0aXZhdGlvbiwyXSxyZXAoIlRldFIoLSkiLGxlbmd0aChjdXJyZW50LnJlZ3Vsb24uYWN0aXZhdGlvbikpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgY2JpbmQoaGFuZGVsLmZvbGRjaGFuZ2UubWF0cml4W2N1cnJlbnQucmVndWxvbi5hY3RpdmF0aW9uLDNdLHJlcCgiVGV0UigrKSIsbGVuZ3RoKGN1cnJlbnQucmVndWxvbi5hY3RpdmF0aW9uKSkpKQogIAogICAgdGVtcG9yYWwuZm9sZC5jaGFuZ2UubWF0cml4PC1hcy5kYXRhLmZyYW1lKHRlbXBvcmFsLmZvbGQuY2hhbmdlLm1hdHJpeCkKICAgIGNvbG5hbWVzKHRlbXBvcmFsLmZvbGQuY2hhbmdlLm1hdHJpeCk8LWMoIkV4cHJlc3Npb24iLCJTdHJhaW4iKQogICAgdGVtcG9yYWwuZm9sZC5jaGFuZ2UubWF0cml4JEV4cHJlc3Npb248LWFzLm51bWVyaWMoYXMudmVjdG9yKHRlbXBvcmFsLmZvbGQuY2hhbmdlLm1hdHJpeCRFeHByZXNzaW9uKSkKICAgIHRlbXBvcmFsLmZvbGQuY2hhbmdlLm1hdHJpeCRTdHJhaW48LWZhY3Rvcih0ZW1wb3JhbC5mb2xkLmNoYW5nZS5tYXRyaXgkU3RyYWluLGxldmVscyA9IGMoIldUKCspIiwiVGV0UigtKSIsIlRldFIoKykiKSxvcmRlcmVkID0gVFJVRSkKICAgICNjcmVhdGUgYmFycGxvdCB3aXRoIGdncGxvdAogICAgYmFycGxvdC5hY3RpdmF0aW9uIDwtIGdncGxvdCh0ZW1wb3JhbC5mb2xkLmNoYW5nZS5tYXRyaXgsIGFlcyh4PVN0cmFpbiwgeT1FeHByZXNzaW9uLGZpbGw9U3RyYWluKSkgKyAKICAgICAgZ2VvbV9ib3hwbG90KGNvbG9yPSJncmVlbiIpKyB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MjQpKQogICAgcHJpbnQoYmFycGxvdC5hY3RpdmF0aW9uK3NjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1yZXAoIndoaXRlIiwzKSkgKyAgZ2d0aXRsZShwYXN0ZSh0Zi5uYW1lLCItLT4iLGxlbmd0aChjdXJyZW50LnJlZ3Vsb24uYWN0aXZhdGlvbiksImdlbmVzIixzZXA9IiAiKSkpIAogIH0KICAgICNydW4gcmFuZG9tIHBlcm11dGF0aW9uIHRlc3QgZm9yIGVhY2ggY29tcGFyaXNvbiAoZS5nLiwgV1QrVEVUIHZzIFdULVRFVCwgVGV0Ui1URVQgdnMgV1QtVEVULCBldGMuKQogICAgIHByaW50KHBhc3RlKHRmLm5hbWUsIi1XVCtURVQgdnMgV1QtVEVUOiIscGVybXV0YXRpb24uZnVuY3Rpb24oY3VycmVudC5yZWd1bG9uLmFjdGl2YXRpb24sMSksc2VwPSIiKSkKICAgIHByaW50KHBhc3RlKHRmLm5hbWUsIi1UZXRSLVRFVCB2cyBXVC1URVQ6IixwZXJtdXRhdGlvbi5mdW5jdGlvbihjdXJyZW50LnJlZ3Vsb24uYWN0aXZhdGlvbiwyKSxzZXA9IiIpKQogICAgcHJpbnQocGFzdGUodGYubmFtZSwiLVRldFIrVEVUIHZzIFdULVRFVDoiLHBlcm11dGF0aW9uLmZ1bmN0aW9uKGN1cnJlbnQucmVndWxvbi5hY3RpdmF0aW9uLDMpLHNlcD0iIikpCiAgfQp9CmBgYAoyLjMgRXZhbHVhdGluZyBvdmVybGFwIGJldHdlZW4gREVHcyBpbiBUZXRSIGFkYXB0aXZlIHJlc3BvbnNlIGFuZCBhcmNBIEtPIGluIGFuYWVyb2JpYyBncm93dGggKEdFTyBhY2Nlc3Npb24gSUQ6IEdTRTExMDcpCmBgYHtyfQojdHJhbnNjcmlwdGlvbmFsIGRhdGEgZm9yIGFyY0EgS08gd2FzIHNvdXJjZWQgZnJvbSBDb3ZlcnQgZXQgYWwuIChOYXR1cmUgMjAwNCkKYXJjQS5rby5tYXRyaXguY292ZXJ0PC1yZWFkLmNzdigiLi4vRGF0YS9EaWZmZXJlbnRpYWxfZXhwcmVzc2lvbl9hbmFseXNpcy9HRU9fQ292ZXJ0MjAwNC9hcmNBX2tvX0NvdmVydDIwMDQuY3N2IixoZWFkZXI9VCxyb3cubmFtZXMgPSAxKQojc2VsZWN0IHJlcGxpY2F0ZXMgZm9yIFdUIGFuZCBhcmNBIEtPIGluIGFuYWVyb2JpYyBjb25kaXRpb24KYXJjQS5rby5tYXRyaXguY292ZXJ0PC1hcmNBLmtvLm1hdHJpeC5jb3ZlcnRbLGMoImFuYV93dDEiLCJhbmFfd3QyIiwiYW5hX3d0MyIsImFuYV93dDQiLCJhbmFfYXJjQTEiLCJhbmFfYXJjQTIiLCJhbmFfYXJjQTMiKV0KI3JlbmFtZSBjb2x1bW5zCmNvbG5hbWVzKGFyY0Eua28ubWF0cml4LmNvdmVydCk8LWMoImFuYWVyb2JpY193dDEiLCJhbmFlcm9iaWNfd3QyIiwiYW5hZXJvYmljX3d0MyIsImFuYWVyb2JpY193dDQiLCJhbmFlcm9iaWNfYXJjQTEiLCJhbmFlcm9iaWNfYXJjQTIiLCJhbmFlcm9iaWNfYXJjQTMiKQojcmVhZCBtaWNyb2FycmF5IHByb2JlcyB0byBsb2NpIG1hcAphcmNBLm1pY3JvYXJyYXkucHJvYmVzLmxvY2kubWFwPC1yZWFkLmNzdigiLi4vRGF0YS9EaWZmZXJlbnRpYWxfZXhwcmVzc2lvbl9hbmFseXNpcy9HRU9fQ292ZXJ0MjAwNC9hcmNBX2NvdmVydDIwMDRfcHJvYmVzX2dlbmVfbWFwLmNzdiIpCiNmaWx0ZXIgb3V0IHRob3NlIGdlbmVzIG5vdCBpbmNsdWRlZCBpbiB0aGUgZXhwcmVzc2lvbiBtYXRyaXggZm9yIFdUIGFuZCBUZXRSIHByZXZpb3VzbHkgYW5hbHl6ZWQKYXJjQS5taWNyb2FycmF5LnByb2Jlcy5sb2NpLm1hcDwtYXJjQS5taWNyb2FycmF5LnByb2Jlcy5sb2NpLm1hcFthcmNBLm1pY3JvYXJyYXkucHJvYmVzLmxvY2kubWFwJE9SRiAlaW4lIHJvd25hbWVzKGhhbmRlbC5ub3JtYWxpemVkLm1hdHJpeCksXQojdGhpcyB3aWxsIGJlIHRoZSBmaW5hbCBtYXRyaXggd2l0aCBsb2N1cyB0YWdzIGFzIHJvd25hbWVzCmZpbmFsLmFyY0Eua28ubWF0cml4LmNvdmVydDwtYygpCiNzdG9yZSBzZXQgb2YgZ2VuZXMgcHJlc2VudCBpbiB0aGUgcmVzdWx0aW5nIGV4cHJlc3Npb24gbWF0cml4CmdlbmVzLmluY2x1ZGVkLmluLmNvdmVydC5kYXRhPC1jKCkKI2NoYW5nZSBwcm9iZSBuYW1lcyB0byBsb2NpCmZvcihnIGluIDE6bnJvdyhhcmNBLm1pY3JvYXJyYXkucHJvYmVzLmxvY2kubWFwKSkKewogIGN1cnJlbnQuZ2VuZTwtYXMuY2hhcmFjdGVyKGFyY0EubWljcm9hcnJheS5wcm9iZXMubG9jaS5tYXAkT1JGW2ddKQogIGdlbmVzLmluY2x1ZGVkLmluLmNvdmVydC5kYXRhPC1jKGdlbmVzLmluY2x1ZGVkLmluLmNvdmVydC5kYXRhLGN1cnJlbnQuZ2VuZSkKICBjdXJyZW50LmdlbmUucG9zaXRpb248LWdyZXAoY3VycmVudC5nZW5lLHJvd25hbWVzKGFyY0Eua28ubWF0cml4LmNvdmVydCkpCiAgZmluYWwuYXJjQS5rby5tYXRyaXguY292ZXJ0PC1yYmluZChmaW5hbC5hcmNBLmtvLm1hdHJpeC5jb3ZlcnQsYXJjQS5rby5tYXRyaXguY292ZXJ0W2N1cnJlbnQuZ2VuZS5wb3NpdGlvbixdKQp9CnJvd25hbWVzKGZpbmFsLmFyY0Eua28ubWF0cml4LmNvdmVydCk8LWdlbmVzLmluY2x1ZGVkLmluLmNvdmVydC5kYXRhCiNsb2cyIHRyYW5zZm9ybSB0aGUgbWljcm9hcnJheSBkYXRhCmZpbmFsLmFyY0Eua28ubWF0cml4LmNvdmVydDwtbG9nMihmaW5hbC5hcmNBLmtvLm1hdHJpeC5jb3ZlcnQpCiNwZXJmb3JtIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2lzIChhcyBwcmV2aW91c2x5IGRvbmUgYWJvdmUpCmFyY0Eua28ucmVzcG9uc2UuY292ZXJ0PC1iYXllc1QoZmluYWwuYXJjQS5rby5tYXRyaXguY292ZXJ0LG51bUMgPSA0LG51bUUgPSAzLGNvbmYgPSA3LGRvTXVsdHRlc3QgPSBUKQojREVHcyBkdWUgdG8gYXJjQSBkZWxldGlvbgphcmNBLmRlZ3MuY292ZXJ0PC1yb3duYW1lcyhhcmNBLmtvLnJlc3BvbnNlLmNvdmVydClbd2hpY2goYXJjQS5rby5yZXNwb25zZS5jb3ZlcnQkQkggPCAwLjA1ICYgYWJzKGFyY0Eua28ucmVzcG9uc2UuY292ZXJ0JG1lYW5DIC0gYXJjQS5rby5yZXNwb25zZS5jb3ZlcnQkbWVhbkUpPjEpXQojZGVmaW5lIG92ZXJsYXAgYmV0d2VlbiBERUdzIGluIGFyY0EgS08gYW5kIFRldFIgcmVzcG9uc2UgdG8gdGV0cmFjeWNsaW5lCm92ZXJsYXBwaW5nLkRFR3M8LWludGVyc2VjdChhcmNBLmRlZ3MuY292ZXJ0LHRldFIucmVzcG9uc2UuZGVncykKI2V2YWx1dGUgb3ZlcmxhcCBzaWduaWZpY2FuY2Ugd2l0aCBoeXBlcmdlb21ldHJpYyB0ZXN0IApvdmVybGFwLnB2YWx1ZTwtcGh5cGVyKGxlbmd0aChvdmVybGFwcGluZy5ERUdzKS0xLGxlbmd0aChhcmNBLmRlZ3MuY292ZXJ0KSxucm93KGFyY0Eua28ucmVzcG9uc2UuY292ZXJ0KS1sZW5ndGgoYXJjQS5kZWdzLmNvdmVydCksbGVuZ3RoKGludGVyc2VjdCh0ZXRSLnJlc3BvbnNlLmRlZ3Mscm93bmFtZXMoYXJjQS5rby5yZXNwb25zZS5jb3ZlcnQpKSksbG93ZXIudGFpbCA9IEYpCnByaW50KHBhc3RlKCJPdmVybGFwIHAtdmFsdWU9IixvdmVybGFwLnB2YWx1ZSxzZXA9IiIpKQpgYGAKMy4xIEZpZyAzQSAoaW5pdGlhbCBhbmFseXNpcyBvZiBiYXJjb2RlIHNlcXVlbmNpbmcgZGF0YSBvZiBnZW5vbWUtd2lkZSBzaW5nbGUgZ2VuZSBLTyBsaWJyYXJ5IGdyb3d0aCBjb21wZXRpdGlvbiBhc3NheXMpCmBgYHtyfQojcmVhZCBjb3VudHMgcGVyIGRlc2lnbiBmb3IgVGV0UiBLTyBsaWJyYXJ5ICg0IGJpb2xvZ2ljYWwgcmVwbGljYXRlcyBwZXIgdGltZSBwb2ludCkKI3RoaXMgaXMgdGhlIG91dHB1dCBvZiB0aGUgSW5zY3JpcHRhUmVzb2x2ZXIgIHNvZnR3YXJlIAp0ZXRSLmtvLmxpYnJhcnkucmVhZHM8LXJlYWQuY3N2KCIuLi9EYXRhL0tPX2xpYnJhcnlfY29tcGV0aXRpb24vcmF3X2tvX2NvdW50X2RhdGEvVGV0Ui9hMDVoL2EwNWhfZGVzaWduX3JlcG9ydC5jc3YiLGhlYWRlcj1UKQojZGVmaW5lIHVuaXF1ZSBzYW1wbGVzIChpLmUuLCBjb21iaW5hdGlvbnMgb2Ygc3RyYWluIHggcmVwbGljYXRlIHggdHJlYXRtZW50IHggdGltZSBwb2ludCkKI3RoZSBmb2xsb3dpbmcgbm90YXRpb24gd2FzIHVzZWQgdG8gbGFiZWwgdGhlIHNhbXBsZXM6IHN0cmFpbiAodGV0UiBvciB3dCktSyhmb3IgS08pe2EsYixjLGR9KGNvcnJlc3BvbmRpbmcgdG8gdGhlIGJpb2xvZ2ljYWwgcmVwbGljYXRlKS0ncGx1cycgb3IgJ21pbnVzJyB0ZXRyYWN5Y2xpbmUgLSB7MSwyLDN9IGNvcnJlc3BvbmRpbmcgdG8gdGhlIGdyb3d0aCBjeWNsZSAoaS5lLiwgVDEsIFQyLCBUMykKIzAtcGx1c1RldCBhbmQgMC1taW51c1RldCBjb3JyZXNwb25kIHRvIFQwIGFuZCB0aGV5IGFyZSB0aGUgc2FtZSBzYW1wbGUgKGVnLCBUZXRSLUthLW1pbnVzVGV0IGlzIHRoZSBzYW1lIGFzIFRldFItS2EtMC1wbHVzVGV0KSAKI1QwIHNhbXBsZXMgd2VyZSBkdXBsaWNhdGVkIHdoZW4gcHJvY2Vzc2luZyB0aGUgZGF0YSB0byBmYWNpbGl0YXRlICh0cmVhdG1lbnQtc3BlY2lmaWMpIGRvd25zdHJlYW0gYW5hbHlzZXMgICAKdGV0Ui5rby5saWJyYXJ5LnNhbXBsZXM8LXVuaXF1ZSh0ZXRSLmtvLmxpYnJhcnkucmVhZHMkU2FtcGxlTmFtZSkKI2RlZmluZSBLTyBkZXNpZ25zCnRldFIua28ubGlicmFyeS5kZXNpZ25zPC11bmlxdWUodGV0Ui5rby5saWJyYXJ5LnJlYWRzJERlc2lnbklkKQojY3JlYXRlIHJlYWQgY291bnQgbWF0cml4IHRoYXQgaW5jbHVkZXMgYSBjb2x1bW4gd2l0aCB0aGUgbmFtZSBvZiB0aGUgZ2VuZSBhc3NvY2lhdGVkIHdpdGggZWFjaCBLTyBkZXNpZ24KI3RldFIua28ubGlicmFyeS5jb3VudC5tYXRyaXg8LW1hdHJpeChuY29sPWxlbmd0aCh0ZXRSLmtvLmxpYnJhcnkuc2FtcGxlcykrMSxucm93PWxlbmd0aCh0ZXRSLmtvLmxpYnJhcnkuZGVzaWducyksMCwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltbmFtZXMgPSBsaXN0KHRldFIua28ubGlicmFyeS5kZXNpZ25zLGMoImdlbmUiLHRldFIua28ubGlicmFyeS5zYW1wbGVzKSkpCiNsb29wIHRvIGZpbGwgb3V0IHRoZSBjb3VudCBtYXRyaXgKI2ZvcihzIGluIHRldFIua28ubGlicmFyeS5zYW1wbGVzKQojewojICBwcmludChzKQojICBmb3IoZCBpbiB0ZXRSLmtvLmxpYnJhcnkuZGVzaWducykKIyAgewojICAgIGN1cnJlbnQucG9zaXRpb248LXdoaWNoKHRldFIua28ubGlicmFyeS5yZWFkcyRTYW1wbGVOYW1lPT1zICYgdGV0Ui5rby5saWJyYXJ5LnJlYWRzJERlc2lnbklkPT1kKQojICAgIGN1cnJlbnQuY291bnQ8LXRldFIua28ubGlicmFyeS5yZWFkc1tjdXJyZW50LnBvc2l0aW9uLCJEZXNpZ25Db3VudCJdCiMgICAgdGV0Ui5rby5saWJyYXJ5LmNvdW50Lm1hdHJpeFthcy5jaGFyYWN0ZXIoZCksc108LSBjdXJyZW50LmNvdW50CiMgICAgdGV0Ui5rby5saWJyYXJ5LmNvdW50Lm1hdHJpeFthcy5jaGFyYWN0ZXIoZCksImdlbmUiXTwtdGV0Ui5rby5saWJyYXJ5LnJlYWRzW2N1cnJlbnQucG9zaXRpb24sIkRlc2lnbl9UYXJnZXROYW1lIl0KIyAgfQojfQojdGV0Ui5rby5saWJyYXJ5LmNvdW50Lm1hdHJpeC53aXRoLmdlbmUuaW5mbzwtdGV0Ui5rby5saWJyYXJ5LmNvdW50Lm1hdHJpeAojbG9hZCBwcmV2aW91c2x5IGNvbXBpbGVkICh3aXRoIGNvZGUgc2hvd24gYWJvdmUpIFRldFIgS08gbGlicmFyeSByZWFkIGNvdW50IG1hdHJpeCAKbG9hZCgiLi4vRGF0YS9LT19saWJyYXJ5X2NvbXBldGl0aW9uL3Byb2Nlc3NlZF9jb3VudF9kYXRhL3RldFIua28ubGlicmFyeS5jb3VudC5tYXRyaXgud2l0aC5nZW5lLmluZm8uUkRhdGEiKQojcmUtb3JnYW5pemUgY29sdW1ucyAoaWUsIHNhbXBsZSByZXBsaWNhdGVzKQp0ZXRSLmtvLnJlYWQuY291bnRzPC10ZXRSLmtvLmxpYnJhcnkuY291bnQubWF0cml4LndpdGguZ2VuZS5pbmZvWyxjKDEwLDIsMjYsMTgsMTIsNCwyOCwyMCwxMyw1LDI5LDIxLDE0LDYsMzAsMjIsMTUsNywzMSwyMywxNiw4LDMyLDI0LDE3LDksMzMsMjUpXQojY2hhbmdlIGNvbHVtbiBuYW1lcyB0byBhIHNpbXBsZXIgbm90YXRpb246IEN5Y2xlLSgrLy0pVEVULXJlcGxpY2F0ZXthLGIsYyxkfQpjb2xuYW1lcyh0ZXRSLmtvLnJlYWQuY291bnRzKTwtcGFzdGUocmVwKGMoIkMwIiwiQzEtVEVULSIsIkMyLVRFVC0iLCJDMy1URVQtIiwiQzErVEVULSIsIkMyK1RFVC0iLCJDMytURVQtIiksZWFjaD00KSxsZXR0ZXJzWzE6NF0sc2VwPSIiKQojQ2kgaW5kaWNhdGVzIGN5Y2xlICMgaSBpbiB0aGUgY29tcGV0aXRpb24gYXNzYXkuIFRoaXMgbWVhbnMgdGhhdCBDMD10MCwgQzE9dDEsIGV0Yy4KI3JlbW92ZSB0aGUgY29sdW1uIHdpdGggZ2VuZSBuYW1lcyB0byBjcmVhdGUgYSBuZXcgbWF0cml4IHRoYXQgb25seSBjb250YWlucyBudW1lcmljIHZhbHVlcwp0ZXRSLmtvLnJlYWQuY291bnRzLm51bWVyaWM8LWMoKQpmb3IoYyBpbiAxOm5jb2wodGV0Ui5rby5yZWFkLmNvdW50cykpCnsKICB0ZXRSLmtvLnJlYWQuY291bnRzLm51bWVyaWM8LWNiaW5kKHRldFIua28ucmVhZC5jb3VudHMubnVtZXJpYyxhcy5udW1lcmljKHRldFIua28ucmVhZC5jb3VudHNbLGNdKSkKfQpjb2xuYW1lcyh0ZXRSLmtvLnJlYWQuY291bnRzLm51bWVyaWMpPC1jb2xuYW1lcyh0ZXRSLmtvLnJlYWQuY291bnRzKQpyb3duYW1lcyh0ZXRSLmtvLnJlYWQuY291bnRzLm51bWVyaWMpPC1yb3duYW1lcyh0ZXRSLmtvLnJlYWQuY291bnRzKQojcmVwZWF0IHByb2Nlc3MgZm9yIFdUIEtPIGxpYnJhcnkKI3JlYWQgY291bnRzIHBlciBkZXNpZ24gZm9yIFdUIEtPIGxpYnJhcmllcyAoNCBiaW9sb2dpY2FsIHJlcGxpY2F0ZXMgcGVyIHRpbWUgcG9pbnQpCiN0aGlzIGlzIHRoZSBvdXRwdXQgb2YgdGhlIEluc2NyaXB0YVJlc29sdmVyICBzb2Z0d2FyZQp3dC5rby5saWJyYXJ5LnJlYWRzPC1yZWFkLmNzdigiLi4vRGF0YS9LT19saWJyYXJ5X2NvbXBldGl0aW9uL3Jhd19rb19jb3VudF9kYXRhL1dUL2EwNWgvYTA1aF9kZXNpZ25fcmVwb3J0LmNzdiIsaGVhZGVyPVQpCiNkZWZpbmUgdW5pcXVlIHNhbXBsZXMgKHdpdGggc2FtZSBub3RhdGlvbiB1c2VkIGZvciB0aGUgVGV0UiBLTyBsaWJyYXJ5KQp3dC5rby5saWJyYXJ5LnNhbXBsZXM8LXVuaXF1ZSh3dC5rby5saWJyYXJ5LnJlYWRzJFNhbXBsZU5hbWUpCiNkZWZpbmUgS08gZGVzaWducwp3dC5rby5saWJyYXJ5LmRlc2lnbnM8LXVuaXF1ZSh3dC5rby5saWJyYXJ5LnJlYWRzJERlc2lnbklkKQojY3JlYXRlIHJlYWQgY291bnQgbWF0cml4IHRoYXQgaW5jbHVkZXMgYSBjb2x1bW4gd2l0aCB0aGUgbmFtZSBvZiB0aGUgZ2VuZSBhc3NvY2lhdGVkIHdpdGggZWFjaCBLTyBkZXNpZ24KI3d0LmtvLmxpYnJhcnkuY291bnQubWF0cml4PC1tYXRyaXgobmNvbD1sZW5ndGgod3Qua28ubGlicmFyeS5zYW1wbGVzKSsxLG5yb3c9bGVuZ3RoKHd0LmtvLmxpYnJhcnkuZGVzaWducyksMCwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbW5hbWVzID0gbGlzdChhcy5jaGFyYWN0ZXIod3Qua28ubGlicmFyeS5kZXNpZ25zKSxjKCJnZW5lIix3dC5rby5saWJyYXJ5LnNhbXBsZXMpKSkKI2xvb3AgdG8gZmlsbCBvdXQgdGhlIGNvdW50IG1hdHJpeAojZm9yKHMgaW4gd3Qua28ubGlicmFyeS5zYW1wbGVzKQojewojICBwcmludChzKQojICBmb3IoZCBpbiB3dC5rby5saWJyYXJ5LmRlc2lnbnMpCiMgIHsKIyAgY3VycmVudC5wb3NpdGlvbjwtd2hpY2god3Qua28ubGlicmFyeS5yZWFkcyRTYW1wbGVOYW1lPT1zICYgd3Qua28ubGlicmFyeS5yZWFkcyREZXNpZ25JZD09ZCkKIyAgY3VycmVudC5jb3VudDwtd3Qua28ubGlicmFyeS5yZWFkc1tjdXJyZW50LnBvc2l0aW9uLCJEZXNpZ25Db3VudCJdCiMgIHd0LmtvLmxpYnJhcnkuY291bnQubWF0cml4W2FzLmNoYXJhY3RlcihkKSxzXTwtIGN1cnJlbnQuY291bnQKIyAgd3Qua28ubGlicmFyeS5jb3VudC5tYXRyaXhbYXMuY2hhcmFjdGVyKGQpLCJnZW5lIl08LXd0LmtvLmxpYnJhcnkucmVhZHNbY3VycmVudC5wb3NpdGlvbiwiRGVzaWduX1RhcmdldE5hbWUiXQojICB9CiN9CiN3dC5rby5saWJyYXJ5LmNvdW50Lm1hdHJpeC53aXRoLmdlbmUuaW5mbzwtd3Qua28ubGlicmFyeS5jb3VudC5tYXRyaXgKI2xvYWQgcHJldmlvdXNseSBjb21waWxlZCBXVCBLTyBsaWJyYXJ5IHJlYWQgY291bnQgbWF0cml4CmxvYWQoIi4uL0RhdGEvS09fbGlicmFyeV9jb21wZXRpdGlvbi9wcm9jZXNzZWRfY291bnRfZGF0YS93dC5rby5saWJyYXJ5LmNvdW50Lm1hdHJpeC53aXRoLmdlbmUuaW5mby5SRGF0YSIpCiNyZS1vcmdhbml6ZSBjb2x1bW5zIChpZSwgc2FtcGxlIHJlcGxpY2F0ZXMpCnd0LmtvLnJlYWQuY291bnRzPC13dC5rby5saWJyYXJ5LmNvdW50Lm1hdHJpeC53aXRoLmdlbmUuaW5mb1ssYygxMCwyLDI2LDE4LDEyLDQsMjgsMjAsMTMsNSwyOSwyMSwxNCw2LDMwLDIyLDE1LDcsMzEsMjMsMTYsOCwzMiwyNCwxNyw5LDMzLDI1KV0KI2NoYW5nZSBjb2x1bW4gbmFtZXMgdXNpbmcgYSBuZXcgc2ltcGxlciBub3RhdGlvbjogQ3ljbGUtKCsvLSlURVQtcmVwbGljYXRle2EsYixjLGR9CmNvbG5hbWVzKHd0LmtvLnJlYWQuY291bnRzKTwtY29sbmFtZXModGV0Ui5rby5yZWFkLmNvdW50cykKI3JlbW92ZSB0aGUgZ2VuZSBjb2x1bW4gdG8gY3JlYXRlIGEgbmV3IG1hdHJpeCB0aGF0IG9ubHkgY29udGFpbnMgbnVtZXJpYyB2YWx1ZXMKd3Qua28ucmVhZC5jb3VudHMubnVtZXJpYzwtYygpCmZvcihjIGluIDE6bmNvbCh3dC5rby5yZWFkLmNvdW50cykpCnsKICB3dC5rby5yZWFkLmNvdW50cy5udW1lcmljPC1jYmluZCh3dC5rby5yZWFkLmNvdW50cy5udW1lcmljLGFzLm51bWVyaWMod3Qua28ucmVhZC5jb3VudHNbLGNdKSkKfQpjb2xuYW1lcyh3dC5rby5yZWFkLmNvdW50cy5udW1lcmljKTwtY29sbmFtZXMod3Qua28ucmVhZC5jb3VudHMpCnJvd25hbWVzKHd0LmtvLnJlYWQuY291bnRzLm51bWVyaWMpPC1yb3duYW1lcyh3dC5rby5yZWFkLmNvdW50cykKI2RlZmluZSBkZXBsZXRlZCAoaWUsIHVuZGV0ZWN0ZWQpIEtPIGRlc2lnbnMgYXQgZWFjaCB0aW1lIHBvaW50CiNhIEtPIGRlc2lnbiB3YXMgY29uc2lkZXJlZCBub3QgZGV0ZWN0ZWQgYXQgYSB0aW1lIHBvaW50IG9mIGludGVyZXN0IHdoZW4gYWxsIGZvdXIgYmlvbG9naWNhbCByZXBsaWNhdGVzIGhhZCBsZXNzIHRoYW4gMTAgcmVhZHMgZm9yIHRoZSBjb3JyZXNwb25kaW5nIEtPIGRlc2lnbiAKI2luaXRpYWxpemUgbGlzdCB0byBzdG9yZSBLTyBkZXNpZ25zIGxhYmVsZWQgYXMgZGVwbGV0ZWQgaW4gVGV0UiBsaWJyYXJ5CnRldFIuZGVwbGV0ZWQuZGVzaWducy50aW1lLnNlcmllczwtTlVMTAp0ZXRSLmRlcGxldGVkLmRlc2lnbnMudGltZS5zZXJpZXNbYygiVDAiLCJUMSgtKSIsIlQyKC0pIiwiVDMoLSkiLCJUMSgrKSIsIlQyKCspIiwiVDMoKykiKV08LWxpc3QoTlVMTCkKI2RlZmluZSB2ZWN0b3Igd2l0aCB0b3RhbCBudW1iZXIgb2YgZGV0ZWN0ZWQgS08gZGVzaWducyBwZXIgc2FtcGxlL3RpbWUgcG9pbnQKdGV0Ui5ub24uZGVwbGV0ZWQuZGVzaWducy52ZWN0b3I8LWMoKQojYSBsb29wIHRvIGRlZmluZSBkZXBsZXRlZCBLTyBkZXNpZ25zIGF0IGVhY2ggcG9pbnQKZm9yKHRldFIuc2FtcGxlIGluIDE6NykKewogIGRlcGxldGVkLmtvLmRlc2lnbnMuY3VycmVudC5zYW1wbGU8LWMoKQogICN0aGUgZGVzaWducyAnNTAwOTU1NjUzJyBhbmQgJzUwMDk1NTY1NCcgYXJlIGV4Y2x1ZGVkIGZyb20gdGhpcyBhbmFseXNpcyBiZWNhdXNlIHRoZXkgd2VyZSB1c2VkIGFzIGludGVybmFsIGNvbnRyb2xzIGFuZCB0aGV5IGFyZSBub3QgYXNzb2NpYXRlZCB3aXRoIGFueSBnZW5lCiAgZm9yKGtvLmRlc2lnbiBpbiBzZXRkaWZmKHRldFIua28ubGlicmFyeS5kZXNpZ25zLGMoIjUwMDk1NTY1MyIsIjUwMDk1NTY1NCIpKSkKICB7CiAgICBpZihtYXgodGV0Ui5rby5yZWFkLmNvdW50cy5udW1lcmljW2FzLmNoYXJhY3Rlcihrby5kZXNpZ24pLCgoNCp0ZXRSLnNhbXBsZSktMyk6KDQqdGV0Ui5zYW1wbGUpXSk8MTApCiAgewogICAgZGVwbGV0ZWQua28uZGVzaWducy5jdXJyZW50LnNhbXBsZTwtYyhkZXBsZXRlZC5rby5kZXNpZ25zLmN1cnJlbnQuc2FtcGxlLGtvLmRlc2lnbikKICB9CiAgfQogIHRldFIuZGVwbGV0ZWQuZGVzaWducy50aW1lLnNlcmllc1tbdGV0Ui5zYW1wbGVdXTwtZGVwbGV0ZWQua28uZGVzaWducy5jdXJyZW50LnNhbXBsZQogIHRldFIubm9uLmRlcGxldGVkLmRlc2lnbnMudmVjdG9yPC1jKHRldFIubm9uLmRlcGxldGVkLmRlc2lnbnMudmVjdG9yLDgyNzEtbGVuZ3RoKGRlcGxldGVkLmtvLmRlc2lnbnMuY3VycmVudC5zYW1wbGUpKQp9Cm5hbWVzKHRldFIubm9uLmRlcGxldGVkLmRlc2lnbnMudmVjdG9yKTwtbmFtZXModGV0Ui5kZXBsZXRlZC5kZXNpZ25zLnRpbWUuc2VyaWVzKQojc2FtZSBhbmFseXNpcyBmb3IgV1QKI2luaXRpYWxpemUgbGlzdCB0byBzdG9yZSBLTyBkZXNpZ25zIGxhYmVsZWQgYXMgZGVwbGV0ZWQgaW4gV1QgbGlicmFyeQp3dC5kZXBsZXRlZC5kZXNpZ25zLnRpbWUuc2VyaWVzPC1OVUxMCnd0LmRlcGxldGVkLmRlc2lnbnMudGltZS5zZXJpZXNbYygiVDAiLCJUMSgtKSIsIlQyKC0pIiwiVDMoLSkiLCJUMSgrKSIsIlQyKCspIiwiVDMoKykiKV08LWxpc3QoTlVMTCkKI2RlZmluZSB2ZWN0b3Igd2l0aCB0b3RhbCBudW1iZXIgb2YgZGV0ZWN0ZWQgS08gZGVzaWducyBwZXIgc2FtcGxlL3RpbWUgcG9pbnQKd3Qubm9uLmRlcGxldGVkLmRlc2lnbnMudmVjdG9yPC1jKCkKZm9yKHd0LnNhbXBsZSBpbiAxOjcpCnsKICBkZXBsZXRlZC5kZXNpZ25zLmN1cnJlbnQuc2FtcGxlPC1jKCkKICBmb3Ioa28uZGVzaWduIGluIHNldGRpZmYod3Qua28ubGlicmFyeS5kZXNpZ25zLGMoIjUwMDk1NTY1MyIsIjUwMDk1NTY1NCIpKSkKICB7CiAgICBpZihtYXgod3Qua28ucmVhZC5jb3VudHMubnVtZXJpY1thcy5jaGFyYWN0ZXIoa28uZGVzaWduKSwoKDQqd3Quc2FtcGxlKS0zKTooNCp3dC5zYW1wbGUpXSk8MTApCiAgewogICAgZGVwbGV0ZWQuZGVzaWducy5jdXJyZW50LnNhbXBsZTwtYyhkZXBsZXRlZC5kZXNpZ25zLmN1cnJlbnQuc2FtcGxlLGtvLmRlc2lnbikKICB9CiAgfQogIHd0LmRlcGxldGVkLmRlc2lnbnMudGltZS5zZXJpZXNbW3d0LnNhbXBsZV1dPC1kZXBsZXRlZC5kZXNpZ25zLmN1cnJlbnQuc2FtcGxlCiAgd3Qubm9uLmRlcGxldGVkLmRlc2lnbnMudmVjdG9yPC1jKHd0Lm5vbi5kZXBsZXRlZC5kZXNpZ25zLnZlY3Rvciw4MjcxLWxlbmd0aChkZXBsZXRlZC5kZXNpZ25zLmN1cnJlbnQuc2FtcGxlKSkKfQpuYW1lcyh3dC5ub24uZGVwbGV0ZWQuZGVzaWducy52ZWN0b3IpPC1uYW1lcyh3dC5kZXBsZXRlZC5kZXNpZ25zLnRpbWUuc2VyaWVzKQojY3JlYXRlIGxlZnQgcGFuZWwgb2YgRmlnLiAzQQpwYXIobWZyb3c9YygxLDIpKQojcGxvdCBudW1iZXIgb2YgZGV0ZWN0ZWQgS08gZGVzaWducyBmb3IgVGV0UigtVEVUKQpwbG90KHg9MDozLHk9dGV0Ui5ub24uZGVwbGV0ZWQuZGVzaWducy52ZWN0b3JbMTo0XSx0eXBlPSJvIix4bGFiPSJDeWNsZSIsCiAgICAgeWxhYj0iIyBtdXRhbnQgZGVzaWducyIsY29sPSJyZWQiLHlsaW09Yyg1MDAwLDgwNTApLGx0eT0yLHBjaD0yMCxjZXg9MS41LGNleC5sYWI9MS41LCBjZXguYXhpcz0xLjUpCiNhZGQgbnVtYmVyIG9mIGRldGVjdGVkIEtPIGRlc2lnbnMgZm9yIFRldFIoK1RFVCkKcG9pbnRzKHg9MDozLHk9dGV0Ui5ub24uZGVwbGV0ZWQuZGVzaWducy52ZWN0b3JbYygxLDU6NyldLHR5cGU9Im8iLGNvbD0icmVkNCIscGNoPTIwKQojYWRkIG51bWJlciBvZiBkZXRlY3RlZCBLTyBkZXNpZ25zIGZvciBXVCgtVEVUKQpwb2ludHMoeD0wOjMseT13dC5ub24uZGVwbGV0ZWQuZGVzaWducy52ZWN0b3JbMTo0XSx0eXBlPSJvIixjb2w9ImJsdWUiLGx0eT0yLHBjaD0yMCkKI2FkZCBudW1iZXIgb2YgZGV0ZWN0ZWQgS08gZGVzaWducyBmb3IgV1QoK1RFVCkKcG9pbnRzKHg9MDozLHk9d3Qubm9uLmRlcGxldGVkLmRlc2lnbnMudmVjdG9yW2MoMSw1OjcpXSx0eXBlPSJvIixjb2w9ImJsdWU0IixwY2g9MjApCmxlZ2VuZCh4PTAseT02ODAwLGxlZ2VuZD1jKCJUZXRSKCspIiwiVGV0UigtKSIsIldUKCspIiwiV1QoLSkiKSxjZXg9MS4xLGNvbD1jKCJyZWQ0IiwicmVkIiwiYmx1ZTQiLCJibHVlIikscGNoPXJlcCgyMCw0KSxib3gubHdkID0gMCxsdHk9YygxLDIsMSwyKSkKI3BlcmZvcm0gc2ltaWxhciBhbmFseXNpcyB0byBpZGVudGlmeSBnZW5lcyB3aG9zZSBLT3Mgd2VyZSB1bmRldGVjdGFibGUKI2EgZ2VuZSB3YXMgY29uc2lkZXJlZCB1bmRldGVjdGVkIChpZSxkZXBsZXRlZCkgaWYgaXRzIHR3byBLTyBkZXNpZ25zIHdlcmUgbGFiZWxlZCBhcyBkZXBsZXRlZCBpbiB0aGUgcHJldmlvdXMgYW5hbHlzaXMKI2luaXRpYWxpemUgbGlzdCB0byBzdG9yZSBuYW1lIG9mIGdlbmVzIGxhYmVsZWQgYXMgZGVwbGV0ZWQgaW4gVGV0UiBsaWJyYXJ5CnRldFIuZGVwbGV0ZWQuZ2VuZXM8LU5VTEwKdGV0Ui5kZXBsZXRlZC5nZW5lc1tjKCJUMCIsIlQxKC0pIiwiVDIoLSkiLCJUMygtKSIsIlQxKCspIiwiVDIoKykiLCJUMygrKSIpXTwtbGlzdChOVUxMKQojZGVmaW5lIHZlY3RvciB3aXRoIHRvdGFsIG51bWJlciBvZiBkZXRlY3RlZCBnZW5lcyBwZXIgc2FtcGxlL3RpbWUgcG9pbnQKdGV0Ui5ub24uZGVwbGV0ZWQuZ2VuZXMuY291bnQudmVjdG9yPC1jKCkKZm9yKHRldFIuc2FtcGxlIGluIDE6NykKewogICNLTyBkZXNpZ25zIGxhYmVsZWQgYXMgZGVwbGV0ZWQgaW4gY3VycmVudCBzYW1wbGUKICBkZXBsZXRlZC5kZXNpZ25zLmN1cnJlbnQuc2FtcGxlPC10ZXRSLmRlcGxldGVkLmRlc2lnbnMudGltZS5zZXJpZXNbW3RldFIuc2FtcGxlXV0KICAjY291bnQgbnVtYmVyIG9mIGRlcGxldGVkIGRlc2lnbnMgYXNzb2NpYXRlZCB3aXRoIGVhY2ggZ2VuZQogIGRlcGxldGVkLmRlc2lnbi50by5nZW5lLm1hcDwtdGV0Ui5rby5saWJyYXJ5LmNvdW50Lm1hdHJpeC53aXRoLmdlbmUuaW5mb1t3aGljaChyb3duYW1lcyh0ZXRSLmtvLmxpYnJhcnkuY291bnQubWF0cml4LndpdGguZ2VuZS5pbmZvKSVpbiVkZXBsZXRlZC5kZXNpZ25zLmN1cnJlbnQuc2FtcGxlKSwiZ2VuZSJdCiAgdGVtcG9yYWwuZ2VuZS5jb3VudC50YWJsZTwtdGFibGUoZGVwbGV0ZWQuZGVzaWduLnRvLmdlbmUubWFwKQogICNkZWZpbmUgc2V0IG9mIGRlcGxldGVkIGdlbmVzCiAgdGV0Ui5kZXBsZXRlZC5nZW5lc1tbdGV0Ui5zYW1wbGVdXTwtbmFtZXMod2hpY2godGVtcG9yYWwuZ2VuZS5jb3VudC50YWJsZT09MikpCiAgdGV0Ui5ub24uZGVwbGV0ZWQuZ2VuZXMuY291bnQudmVjdG9yPC1jKHRldFIubm9uLmRlcGxldGVkLmdlbmVzLmNvdW50LnZlY3Rvciw0MTUzLWxlbmd0aCh0ZXRSLmRlcGxldGVkLmdlbmVzW1t0ZXRSLnNhbXBsZV1dKSkKfQojaW5pdGlhbGl6ZSBsaXN0IHRvIHN0b3JlIG5hbWVzIG9mIGdlbmVzIGxhYmVsZWQgYXMgZGVwbGV0ZWQgaW4gV1QgbGlicmFyeQp3dC5kZXBsZXRlZC5nZW5lczwtTlVMTAp3dC5kZXBsZXRlZC5nZW5lc1tjKCJUMCIsIlQxKC0pIiwiVDIoLSkiLCJUMygtKSIsIlQxKCspIiwiVDIoKykiLCJUMygrKSIpXTwtbGlzdChOVUxMKQojZGVmaW5lIHZlY3RvciB3aXRoIHRvdGFsIG51bWJlciBvZiBkZXRlY3RlZCBnZW5lcyBwZXIgc2FtcGxlL3RpbWUgcG9pbnQKd3Qubm9uLmRlcGxldGVkLmdlbmVzLmNvdW50LnZlY3RvcjwtYygpCmZvcih3dC5zYW1wbGUgaW4gMTo3KQp7CiAgI0tPIGRlc2lnbnMgbGFiZWxlZCBhcyBkZXBsZXRlZCBpbiBjdXJyZW50IHNhbXBsZQogIGRlcGxldGVkLmRlc2lnbnMuY3VycmVudC5zYW1wbGU8LXd0LmRlcGxldGVkLmRlc2lnbnMudGltZS5zZXJpZXNbW3d0LnNhbXBsZV1dCiAgI2NvdW50IG51bWJlciBvZiBkZXBsZXRlZCBkZXNpZ25zIGFzc29jaWF0ZWQgd2l0aCBlYWNoIGdlbmUKICBkZXBsZXRlZC5kZXNpZ24udG8uZ2VuZS5tYXA8LXd0LmtvLmxpYnJhcnkuY291bnQubWF0cml4LndpdGguZ2VuZS5pbmZvW3doaWNoKHJvd25hbWVzKHd0LmtvLmxpYnJhcnkuY291bnQubWF0cml4LndpdGguZ2VuZS5pbmZvKSVpbiVkZXBsZXRlZC5kZXNpZ25zLmN1cnJlbnQuc2FtcGxlKSwiZ2VuZSJdCiAgdGVtcG9yYWwuZ2VuZS5jb3VudC50YWJsZTwtdGFibGUoZGVwbGV0ZWQuZGVzaWduLnRvLmdlbmUubWFwKQogICNkZWZpbmUgc2V0IG9mIGRlcGxldGVkIGdlbmVzCiAgd3QuZGVwbGV0ZWQuZ2VuZXNbW3d0LnNhbXBsZV1dPC1uYW1lcyh3aGljaCh0ZW1wb3JhbC5nZW5lLmNvdW50LnRhYmxlPT0yKSkKICB3dC5ub24uZGVwbGV0ZWQuZ2VuZXMuY291bnQudmVjdG9yPC1jKHd0Lm5vbi5kZXBsZXRlZC5nZW5lcy5jb3VudC52ZWN0b3IsNDE1My1sZW5ndGgod3QuZGVwbGV0ZWQuZ2VuZXNbW3d0LnNhbXBsZV1dKSkKfQojY3JlYXRlIHJpZ2h0IHBhbmVsIG9mIEZpZy4gM0EKI3Bsb3QgbnVtYmVyIG9mIGRldGVjdGVkIGdlbmVzIGZvciBUZXRSKC1URVQpCnBsb3QoeD0wOjMseT10ZXRSLm5vbi5kZXBsZXRlZC5nZW5lcy5jb3VudC52ZWN0b3JbMTo0XSx0eXBlPSJvIix4bGFiPSJDeWNsZSIsCiAgICAgeWxhYj0iIyBkZXRlY3RlZCBnZW5lcyIsY29sPSJyZWQiLHlsaW09YygzMjAwLDQxMjApLGx0eT0yLHBjaD0yMCxjZXg9MS41LGNleC5sYWI9MS41LCBjZXguYXhpcz0xLjUpCiNhZGQgbnVtYmVyIG9mIGRldGVjdGVkIGdlbmVzIGZvciBUZXRSKCtURVQpCnBvaW50cyh4PTA6Myx5PXRldFIubm9uLmRlcGxldGVkLmdlbmVzLmNvdW50LnZlY3RvcltjKDEsNTo3KV0sdHlwZT0ibyIsY29sPSJyZWQ0IixwY2g9MjApCiNhZGQgbnVtYmVyIG9mIGRldGVjdGVkIGdlbmVzIGZvciBXVCgtVEVUKQpwb2ludHMoeD0wOjMseT13dC5ub24uZGVwbGV0ZWQuZ2VuZXMuY291bnQudmVjdG9yWzE6NF0sdHlwZT0ibyIsY29sPSJibHVlIixsdHk9MixwY2g9MjApCiNhZGQgbnVtYmVyIG9mIGRldGVjdGVkIGdlbmVzIGZvciBXVCgrVEVUKQpwb2ludHMoeD0wOjMseT13dC5ub24uZGVwbGV0ZWQuZ2VuZXMuY291bnQudmVjdG9yW2MoMSw1OjcpXSx0eXBlPSJvIixjb2w9ImJsdWU0IixwY2g9MjApCmxlZ2VuZCh4PTAseT0zODAwLGxlZ2VuZD1jKCJUZXRSKCspIiwiVGV0UigtKSIsIldUKCspIiwiV1QoLSkiKSxjZXg9MS4xLGNvbD1jKCJyZWQ0IiwicmVkIiwiYmx1ZTQiLCJibHVlIikscGNoPXJlcCgyMCw0KSxib3gubHdkID0gMCxsdHk9YygxLDIsMSwyKSkKI3ByaW50IHN1bW1hcnkgdGFibGUKb3V0cHV0LnN1bW1hcnk8LWNiaW5kKHRldFIubm9uLmRlcGxldGVkLmRlc2lnbnMudmVjdG9yLHRldFIubm9uLmRlcGxldGVkLmdlbmVzLmNvdW50LnZlY3Rvcix3dC5ub24uZGVwbGV0ZWQuZGVzaWducy52ZWN0b3Isd3Qubm9uLmRlcGxldGVkLmdlbmVzLmNvdW50LnZlY3RvcikKY29sbmFtZXMob3V0cHV0LnN1bW1hcnkpPC1jKCJUZXRSLWRldGVjdGVkIEtPIGRlc2lnbnMiLCJUZXRSLWRldGVjdGVkIGdlbmVzIiwiV1QtZGV0ZWN0ZWQgS08gZGVzaWducyIsIldULWRldGVjdGVkIGdlbmVzIikKcHJpbnQob3V0cHV0LnN1bW1hcnkpCmBgYAozLjIgQ3JlYXRlIEZpZy4gM0IKYGBge3J9CiN3cml0ZSBDU1YgZmlsZSB3aXRoIGdlbmUgbmFtZSBhbmQgbG9jdXMgdGFnIG9mIGFsbCBnZW5lcyBpZGVudGlmaWVkIGFzIGRlcGxldGVkIGluIHRoZSBsYXN0IHRpbWUgcG9pbnQgKFQzKSBvZiBUZXRSK1RFVCBjb21wZXRpdGlvbiBleHBlcmltZW50IGR1ZSB0byB0ZXRyYWN5Y2xpbmUgKHRoaXMgc2V0IGRvZXMgbm90IGluY2x1ZGUgZ2VuZXMgbm90IGRldGVjdGVkIGF0IFQwIG9yIFQzLVRFVCkKI3RoaXMgZmlsZSBpcyB0aGUgaW5wdXQgZm9yIERBVklEIChodHRwczovL2RhdmlkLm5jaWZjcmYuZ292L2hvbWUuanNwKSBmdW5jdGlvbmFsIGFubm90YXRpb24gY2x1c3RlcmluZyBhbmFseXNpcwojZ2VuZXMuZGVwbGV0ZWQuaW4udGV0Ui5kdWUudG8udGV0PC1zZXRkaWZmKHRldFIuZGVwbGV0ZWQuZ2VuZXNbWyJUMygrKSJdXSx1bmlvbih0ZXRSLmRlcGxldGVkLmdlbmVzW1siVDAiXV0sdGV0Ui5kZXBsZXRlZC5nZW5lc1tbIlQzKC0pIl1dKSkKI3dyaXRlLmNzdihmaWxlPSIuLi9EYXRhL0tPX2xpYnJhcnlfY29tcGV0aXRpb24vcHJvY2Vzc2VkX2NvdW50X2RhdGEvdGV0Ul9kZXBsZXRlZF9nZW5lc190M19kdWVfdG9fdGV0cmFjeWNsaW5lLmNzdiIsY2JpbmQoZ2VuZXMuZGVwbGV0ZWQuaW4udGV0Ui5kdWUudG8udGV0LHRyYW5zbGF0ZS5nZW5lLm5hbWUudG8ubG9jdXMoZ2VuZXMuZGVwbGV0ZWQuaW4udGV0Ui5kdWUudG8udGV0KSkpCiNjcmVhdGUgYmFycGxvdCBmb3IgRmlnIDNCICh1c2luZyBEQVZJRCBvdXRwdXQpCnBhcihtZnJvdz1jKDEsMikpCnBsb3QubmV3KCkKYmFycGxvdChjKDExNiw3NCwyOCwyNywyNCwxOCwxNiwxMSwxMSkKICAgICAgICAgICxjZXgubGFiPTEuMjUsY2V4LmF4aXM9MS4yNSxjZXgubmFtZXMgPSAxLHhsYWI9IiMgZ2VuZXMiLApuYW1lcz1jKCJOdWNsZW90aWRlL0FUUCBiaW5kaW5nIiwiUmlib3NvbWUvVHJhbnNsYXRpb24vclJOQS1iaW5kaW5nIiwiTFBTIGJpb3N5bnRoZXNpcyIsIkNlbGwgZGl2aXNpb24iLCJDZWxsIHdhbGwgb3JnLi9jZWxsIHNoYXBlIiwiQmlvc3ludGhlc2lzIG9mIG51Y2xlb3RpZGUgc3VnYXJzIiwiRE5BIHJlcGxpY2F0aW9uIiwiUmlib3NvbWUgYmlvZ2VuZXNpcyIsIlViaXF1aW5vbmUgYmlvc3ludGhlc2lzIiksY29sPXJhaW5ib3coOSksbGFzPTIsaG9yaXogPSBULHhsaW09YygwLDEyMCksbWFpbj0iRmlnLiAzQiIpCmBgYAozLjMgTG9hZCBhbmQgcHJvY2VzcyBBTERFeDIgb3V0cHV0CmBgYHtyfQojdGhlIHNjcmlwdCBiZWxvdyBydW5zIEFMREV4MiBhbmQgZ2VuZXJhdGVzIHJlbGV2YW50IG91dHB1dHMgKGVnLCBUMSB2cyBUMCB3aXRoIGFuZCB3aXRob3V0IHRldHJhY3ljbGluZSBpbiB0aGUgVGV0UiBhbmQgV1QgbGlicmFyaWVzKQojc291cmNlKCJhbGRleDJfYW5hbHlzaXMuUiIpCiNsb2FkIEFMREV4MiBvdXRwdXQKbG9hZCgiLi4vRGF0YS9LT19saWJyYXJ5X2NvbXBldGl0aW9uL3Byb2Nlc3NlZF9jb3VudF9kYXRhL0FMREV4Ml9vdXRwdXQuUkRhdGEiKQojbm90YXRpb24gb2YgdGhlIEFMREV4MiBvdXRwdXQ6IHN0cmFpbih0ZXRSL3d0KS5rby5pcWxyKGZvciBpbnRlci1xdWFydGlsZSBsb2cgcmF0aW8pLmMwKHRoaXMgaXMgVDApLmMjaSh3aGVyZSBpIGlzIDEgb3IgMiBmb3IgVDEgb3IgVDIpLnBsdXMvbWludXModGV0cmFjeWNsaW5lIHRyZWF0bWVudCkKI2Z1bmN0aW9uIHRvIGRlZmluZSBnZW5lcyB3aG9zZSBkZWxldGlvbiBpbXBhY3QgZml0bmVzcyAKI3RoYXQgaXMgZ2VuZXMgZm9yIHdoaWNoIGFsbCBvZiB0aGVpciBub24tZGVwbGV0ZWQgZGVzaWducyB3ZXJlIG92ZXItIG9yIHVuZGVyLXJlcHJlc2VudGVkIGluIHRoZSBBTERFeDIgdGVzdApkZWZpbmUuaGlnaC5jb25maW5kZW5jZS5nZW5lczwtZnVuY3Rpb24oZGVzaWduLnNldCxhbGRleC5vdXRwdXQubWF0cml4LHJlYWQuY291bnQubWF0cml4KQp7CiAgb3V0cHV0PC1jKCkKICAjd2UgbmVlZCB0byBkZWZpbmUgdGhlIGdlbmVzIGFzc29jaWF0ZWQgd2l0aCB0aGUgZGlmZmVyZW50aWFsbHkgYWJ1bmRhbnQgZGVzaWducyAoZGVzaWduLnNldCBkZWZpbmVkIHVzaW5nIEFMREV4MikKICBpbnB1dC5kZXNpZ24udG8uZ2VuZS5tYXA8LXJlYWQuY291bnQubWF0cml4W3doaWNoKHJvd25hbWVzKHJlYWQuY291bnQubWF0cml4KSVpbiVkZXNpZ24uc2V0KSwiZ2VuZSJdCiAgZ2VuZXMuaW4uc2VsZWN0ZWQuZGVzaWduczwtdW5pcXVlKGlucHV0LmRlc2lnbi50by5nZW5lLm1hcCkKICAjd2UgYWxzbyBuZWVkIHRvIGRlZmluZSBob3cgbWFueSBkZXNpZ25zIHdlcmUgYXNzb2NpYXRlZCB3aXRoIGVhY2ggZ2VuZSBpbiBBTERFeDIgaW5wdXQgbWF0cml4IChyb3duYW1lcyBvZiB0aGUgYWxkZXgub3V0cHV0Lm1hdHJpeCkKICBmdWxsLm1hdHJpeC5kZXNpZ24udG8uZ2VuZS5tYXA8LXJlYWQuY291bnQubWF0cml4W3doaWNoKHJvd25hbWVzKHJlYWQuY291bnQubWF0cml4KSVpbiVyb3duYW1lcyhhbGRleC5vdXRwdXQubWF0cml4KSksImdlbmUiXQogICNsb29wIHRvIGV2YWx1YXRlIHdoaWNoIGdlbmVzIHdlcmUgZGlmZmVyZW50aWFsbHkgYWJ1bmRhbnQgCiAgZm9yKGcgaW4gZ2VuZXMuaW4uc2VsZWN0ZWQuZGVzaWducykKICB7CiAgICBpZihsZW5ndGgod2hpY2goaW5wdXQuZGVzaWduLnRvLmdlbmUubWFwPT1nKSk9PWxlbmd0aCh3aGljaChmdWxsLm1hdHJpeC5kZXNpZ24udG8uZ2VuZS5tYXA9PWcpKSkKICAgIHsKICAgICAgb3V0cHV0PC1jKG91dHB1dCxnKQogICAgfQogIH0KICBvdXRwdXQKfSAgCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKI2FkanVzdGVkIHAtdmFsdWUgKHF2YWx1ZSkgYW5kIEFMREV4Mi1lc3RpbWF0ZWQgZWZmZWN0IHRocmVzaG9sZHMgdXNlZCBpbiB0aGUgYW5hbHlzaXMKcXZhbC50aHJlc2hvbGQ8LTAuMQplZmZlY3QudGhyZXNob2xkPC0yCiNwcm9jZXNzIEFMREV4MiBvdXRwdXQgZm9yIFRldFIrVEVUIChUMSkgdnMgVGV0UiAoVDApICh0ZXRSLmtvLmlxbHIuYzAuYzEucGx1cykKI2lkZW50aWZ5IHVuZGVyLXJlcHJlc2VudGVkIChkZWxldGVyaW91cykgS08gZGVzaWducwp0ZXRSLmRlbGV0ZXJpb3VzLmZlYXV0dXJlcy5jMC5jMS5wbHVzPC1yb3duYW1lcyh0ZXRSLmtvLmlxbHIuYzAuYzEucGx1cylbd2hpY2godGV0Ui5rby5pcWxyLmMwLmMxLnBsdXMkd2UuZUJIIDwgcXZhbC50aHJlc2hvbGQgJiB0ZXRSLmtvLmlxbHIuYzAuYzEucGx1cyR3aS5lQkggPCBxdmFsLnRocmVzaG9sZCAmICB0ZXRSLmtvLmlxbHIuYzAuYzEucGx1cyRlZmZlY3QgPCAtMSplZmZlY3QudGhyZXNob2xkKV0KI2RlZmluZSBnZW5lcyB3aG9zZSBkZWxldGlvbnMgd2VyZSBkZWxldGVyaW91cwp0ZXRSLmRlbGV0ZXJpb3VzLmRlbGV0aW9ucy5jMC5jMS5wbHVzLmhpZ2guY29uZmlkZW5jZTwtZGVmaW5lLmhpZ2guY29uZmluZGVuY2UuZ2VuZXMoZGVzaWduLnNldCA9dGV0Ui5kZWxldGVyaW91cy5mZWF1dHVyZXMuYzAuYzEucGx1cywgYWxkZXgub3V0cHV0Lm1hdHJpeCA9IHRldFIua28uaXFsci5jMC5jMS5wbHVzLHJlYWQuY291bnQubWF0cml4ID0gdGV0Ui5rby5saWJyYXJ5LmNvdW50Lm1hdHJpeC53aXRoLmdlbmUuaW5mbykKI2lkZW50aWZ5IG92ZXItcmVwcmVzZW50ZWQgKGJlbmVmaWNpYWwpIEtPIGRlc2lnbnMKdGV0Ui5iZW5lZmljaWFsLmZlYXV0dXJlcy5jMC5jMS5wbHVzPC1yb3duYW1lcyh0ZXRSLmtvLmlxbHIuYzAuYzEucGx1cylbd2hpY2godGV0Ui5rby5pcWxyLmMwLmMxLnBsdXMkd2UuZUJIIDwgcXZhbC50aHJlc2hvbGQgICYgdGV0Ui5rby5pcWxyLmMwLmMxLnBsdXMkd2kuZUJIIDwgcXZhbC50aHJlc2hvbGQgICYgdGV0Ui5rby5pcWxyLmMwLmMxLnBsdXMkZWZmZWN0ID4gZWZmZWN0LnRocmVzaG9sZCldCiNkZWZpbmUgZ2VuZXMgd2hvc2UgZGVsZXRpb25zIHdlcmUgYmVuZWZpY2lhbAp0ZXRSLmJlbmVmaWNpYWwuZGVsZXRpb25zLmMwLmMxLnBsdXMuaGlnaC5jb25maWRlbmNlPC1kZWZpbmUuaGlnaC5jb25maW5kZW5jZS5nZW5lcyhkZXNpZ24uc2V0ID10ZXRSLmJlbmVmaWNpYWwuZmVhdXR1cmVzLmMwLmMxLnBsdXMsIGFsZGV4Lm91dHB1dC5tYXRyaXggPSB0ZXRSLmtvLmlxbHIuYzAuYzEucGx1cyxyZWFkLmNvdW50Lm1hdHJpeCA9IHRldFIua28ubGlicmFyeS5jb3VudC5tYXRyaXgud2l0aC5nZW5lLmluZm8pCiNyZW1vdmUgZ2VuZXMgd2l0aCBLTyBkZXNpZ25zIGxhYmVsZWQgYXMgYmVuZWZpY2lhbCBBTkQgZGVsZXRlcmlvdXMKdGV0Ui5kZWxldGVyaW91cy5kZWxldGlvbnMuYzAuYzEucGx1cy5maW5hbDwtc2V0ZGlmZih0ZXRSLmRlbGV0ZXJpb3VzLmRlbGV0aW9ucy5jMC5jMS5wbHVzLmhpZ2guY29uZmlkZW5jZSx0ZXRSLmJlbmVmaWNpYWwuZGVsZXRpb25zLmMwLmMxLnBsdXMuaGlnaC5jb25maWRlbmNlKQp0ZXRSLmJlbmVmaWNpYWwuZGVsZXRpb25zLmMwLmMxLnBsdXMuZmluYWw8LXNldGRpZmYodGV0Ui5iZW5lZmljaWFsLmRlbGV0aW9ucy5jMC5jMS5wbHVzLmhpZ2guY29uZmlkZW5jZSx0ZXRSLmRlbGV0ZXJpb3VzLmRlbGV0aW9ucy5jMC5jMS5wbHVzLmhpZ2guY29uZmlkZW5jZSkKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojcHJvY2VzcyBBTERFeDIgb3V0cHV0IGZvciBUZXRSK1RFVCAoVDIpIHZzIFRldFIgKFQwKSAodGV0Ui5rby5pcWxyLmMwLmMyLnBsdXMpCiNpZGVudGlmeSB1bmRlci1yZXByZXNlbnRlZCAoZGVsZXRlcmlvdXMpIEtPIGRlc2lnbnMgCnRldFIuZGVsZXRlcmlvdXMuZmVhdXR1cmVzLmMwLmMyLnBsdXM8LXJvd25hbWVzKHRldFIua28uaXFsci5jMC5jMi5wbHVzKVt3aGljaCh0ZXRSLmtvLmlxbHIuYzAuYzIucGx1cyR3ZS5lQkggPCBxdmFsLnRocmVzaG9sZCAgJiB0ZXRSLmtvLmlxbHIuYzAuYzIucGx1cyR3aS5lQkggPCBxdmFsLnRocmVzaG9sZCAmIHRldFIua28uaXFsci5jMC5jMi5wbHVzJGVmZmVjdCA8IC0xKmVmZmVjdC50aHJlc2hvbGQpXQojaWRlbnRpZnkgZ2VuZXMgd2hvc2UgZGVsZXRpb25zIHdlcmUgZGVsZXRlcmlvdXMKdGV0Ui5kZWxldGVyaW91cy5kZWxldGlvbnMuYzAuYzIucGx1cy5oaWdoLmNvbmZpZGVuY2U8LWRlZmluZS5oaWdoLmNvbmZpbmRlbmNlLmdlbmVzKGRlc2lnbi5zZXQgPXRldFIuZGVsZXRlcmlvdXMuZmVhdXR1cmVzLmMwLmMyLnBsdXMsIGFsZGV4Lm91dHB1dC5tYXRyaXggPSB0ZXRSLmtvLmlxbHIuYzAuYzIucGx1cyxyZWFkLmNvdW50Lm1hdHJpeCA9IHRldFIua28ubGlicmFyeS5jb3VudC5tYXRyaXgud2l0aC5nZW5lLmluZm8pCiNpZGVudGlmeSBvdmVyLXJlcHJlc2VudGVkIChiZW5lZmljaWFsKSBLTyBkZXNpZ25zCnRldFIuYmVuZWZpY2lhbC5mZWF1dHVyZXMuYzAuYzIucGx1czwtcm93bmFtZXModGV0Ui5rby5pcWxyLmMwLmMyLnBsdXMpW3doaWNoKHRldFIua28uaXFsci5jMC5jMi5wbHVzJHdlLmVCSCA8IHF2YWwudGhyZXNob2xkICYgdGV0Ui5rby5pcWxyLmMwLmMyLnBsdXMkd2kuZUJIIDwgcXZhbC50aHJlc2hvbGQgJiB0ZXRSLmtvLmlxbHIuYzAuYzIucGx1cyRlZmZlY3QgPiBlZmZlY3QudGhyZXNob2xkKV0KI2lkZW50aWZ5IGdlbmVzIHdob3NlIGRlbGV0aW9ucyB3ZXJlIGJlbmVmaWNpYWwKdGV0Ui5iZW5lZmljaWFsLmRlbGV0aW9ucy5jMC5jMi5wbHVzLmhpZ2guY29uZmlkZW5jZTwtZGVmaW5lLmhpZ2guY29uZmluZGVuY2UuZ2VuZXMoZGVzaWduLnNldCA9dGV0Ui5iZW5lZmljaWFsLmZlYXV0dXJlcy5jMC5jMi5wbHVzLCBhbGRleC5vdXRwdXQubWF0cml4ID0gdGV0Ui5rby5pcWxyLmMwLmMyLnBsdXMscmVhZC5jb3VudC5tYXRyaXggPSB0ZXRSLmtvLmxpYnJhcnkuY291bnQubWF0cml4LndpdGguZ2VuZS5pbmZvKQojcmVtb3ZlIGdlbmVzIHdpdGggbXV0YW50IGRlc2lnbnMgbGFiZWxlZCBhcyBiZW5lZmljaWFsIEFORCBkZWxldGVyaW91cwp0ZXRSLmRlbGV0ZXJpb3VzLmRlbGV0aW9ucy5jMC5jMi5wbHVzLmZpbmFsPC1zZXRkaWZmKHRldFIuZGVsZXRlcmlvdXMuZGVsZXRpb25zLmMwLmMyLnBsdXMuaGlnaC5jb25maWRlbmNlLHRldFIuYmVuZWZpY2lhbC5kZWxldGlvbnMuYzAuYzIucGx1cy5oaWdoLmNvbmZpZGVuY2UpCnRldFIuYmVuZWZpY2lhbC5kZWxldGlvbnMuYzAuYzIucGx1cy5maW5hbDwtc2V0ZGlmZih0ZXRSLmJlbmVmaWNpYWwuZGVsZXRpb25zLmMwLmMyLnBsdXMuaGlnaC5jb25maWRlbmNlLHRldFIuZGVsZXRlcmlvdXMuZGVsZXRpb25zLmMwLmMyLnBsdXMuaGlnaC5jb25maWRlbmNlKQojY29uc29saWRhdGUgcmVzdWx0cyBmb3IgdGhlIFRldFIgbGlicmFyeQojZ2VuZSBkZWxldGlvbnMgd2l0aCBvcHBvc2l0ZSBlZmZlY3RzIGF0IGRpZmZlcmVudCB0aW1lIHBvaW50cyB3ZXJlIG5vdCBjb25zaWRlcmVkCnRldFIuZGVsZXRlcmlvdXMuYWxkZXguY29tcGlsYXRpb248LXNldGRpZmYodW5pb24odGV0Ui5kZWxldGVyaW91cy5kZWxldGlvbnMuYzAuYzEucGx1cy5maW5hbCx0ZXRSLmRlbGV0ZXJpb3VzLmRlbGV0aW9ucy5jMC5jMi5wbHVzLmZpbmFsKSx1bmlvbih0ZXRSLmJlbmVmaWNpYWwuZGVsZXRpb25zLmMwLmMxLnBsdXMuZmluYWwsdGV0Ui5iZW5lZmljaWFsLmRlbGV0aW9ucy5jMC5jMi5wbHVzLmZpbmFsKSkKdGV0Ui5iZW5lZmljaWFsLmFsZGV4LmNvbXBpbGF0aW9uPC1zZXRkaWZmKHVuaW9uKHRldFIuYmVuZWZpY2lhbC5kZWxldGlvbnMuYzAuYzEucGx1cy5maW5hbCx0ZXRSLmJlbmVmaWNpYWwuZGVsZXRpb25zLmMwLmMyLnBsdXMuZmluYWwpLHVuaW9uKHRldFIuZGVsZXRlcmlvdXMuZGVsZXRpb25zLmMwLmMxLnBsdXMuZmluYWwsdGV0Ui5kZWxldGVyaW91cy5kZWxldGlvbnMuYzAuYzIucGx1cy5maW5hbCkpCnByaW50KHBhc3RlKCJUZXRSIGhhZCIsbGVuZ3RoKHRldFIuZGVsZXRlcmlvdXMuYWxkZXguY29tcGlsYXRpb24pLCJnZW5lcyB3aG9zZSBkZWxldGlvbnMgd2VyZSBkZWxldGVyaW91cyIsc2VwPSIgIikpCnByaW50KHBhc3RlKCJUZXRSIGhhZCIsbGVuZ3RoKHRldFIuYmVuZWZpY2lhbC5hbGRleC5jb21waWxhdGlvbiksImdlbmVzIHdob3NlIGRlbGV0aW9ucyB3ZXJlIGJlbmVmaWNpYWwiLHNlcD0iICIpKQojemVybyBLTyBkZXNpZ25zIHdlcmUgaWRlbnRpZmllZCBhcyBkaWZmZXJlbnRpYWxseSBhYnVuZGFudCBhdCBUMSgtVEVUKSBvciBUMigtVEVUKSB2cyBUMAojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiNwcm9jZXNzIEFMREV4MiBvdXRwdXQgZm9yIFdUK1RFVCAoVDEpIHZzIFdUIChUMCkgKHd0LmtvLmlxbHIuYzAuYzEucGx1cykKI2lkZW50aWZ5IHVuZGVyLXJlcHJlc2VudGVkIChkZWxldGVyaW91cykgS08gZGVzaWducwp3dC5kZWxldGVyaW91cy5mZWF1dHVyZXMuYzAuYzEucGx1czwtcm93bmFtZXMod3Qua28uaXFsci5jMC5jMS5wbHVzKVt3aGljaCh3dC5rby5pcWxyLmMwLmMxLnBsdXMkd2UuZUJIIDwgcXZhbC50aHJlc2hvbGQgJiB3dC5rby5pcWxyLmMwLmMxLnBsdXMkd2kuZUJIIDwgcXZhbC50aHJlc2hvbGQgJiB3dC5rby5pcWxyLmMwLmMxLnBsdXMkZWZmZWN0IDwgLTEqZWZmZWN0LnRocmVzaG9sZCldCiNpZGVudGlmeSBnZW5lcyB3aG9zZSBkZWxldGlvbnMgd2VyZSBkZWxldGVyaW91cwp3dC5kZWxldGVyaW91cy5kZWxldGlvbnMuYzAuYzEucGx1cy5oaWdoLmNvbmZpZGVuY2U8LWRlZmluZS5oaWdoLmNvbmZpbmRlbmNlLmdlbmVzKGRlc2lnbi5zZXQgPXd0LmRlbGV0ZXJpb3VzLmZlYXV0dXJlcy5jMC5jMS5wbHVzLCBhbGRleC5vdXRwdXQubWF0cml4ID0gd3Qua28uaXFsci5jMC5jMS5wbHVzLHJlYWQuY291bnQubWF0cml4ID0gd3Qua28ubGlicmFyeS5jb3VudC5tYXRyaXgud2l0aC5nZW5lLmluZm8pCiNpZGVudGlmeSBvdmVyLXJlcHJlc2VudGVkIChiZW5lZmljaWFsKSBLTyBkZXNpZ25zCnd0LmJlbmVmaWNpYWwuZmVhdXR1cmVzLmMwLmMxLnBsdXM8LXJvd25hbWVzKHd0LmtvLmlxbHIuYzAuYzEucGx1cylbd2hpY2god3Qua28uaXFsci5jMC5jMS5wbHVzJHdlLmVCSCA8IHF2YWwudGhyZXNob2xkICYgd3Qua28uaXFsci5jMC5jMS5wbHVzJHdpLmVCSCA8IHF2YWwudGhyZXNob2xkICYgd3Qua28uaXFsci5jMC5jMS5wbHVzJGVmZmVjdCA+IGVmZmVjdC50aHJlc2hvbGQpXQojaWRlbnRpZnkgZ2VuZXMgd2hvc2UgZGVsZXRpb25zIHdlcmUgYmVuZWZpY2lhbAp3dC5iZW5lZmljaWFsLmRlbGV0aW9ucy5jMC5jMS5wbHVzLmhpZ2guY29uZmlkZW5jZTwtZGVmaW5lLmhpZ2guY29uZmluZGVuY2UuZ2VuZXMoZGVzaWduLnNldCA9d3QuYmVuZWZpY2lhbC5mZWF1dHVyZXMuYzAuYzEucGx1cywgYWxkZXgub3V0cHV0Lm1hdHJpeCA9IHd0LmtvLmlxbHIuYzAuYzEucGx1cyxyZWFkLmNvdW50Lm1hdHJpeCA9IHd0LmtvLmxpYnJhcnkuY291bnQubWF0cml4LndpdGguZ2VuZS5pbmZvKQojcmVtb3ZlIGdlbmVzIHdpdGggbXV0YW50IGRlc2lnbnMgaWRlbnRpZmllZCBhcyBib3RoIGJlbmVmaWNpYWwgQU5EIGRlbGV0ZXJpb3VzCnd0LmRlbGV0ZXJpb3VzLmRlbGV0aW9ucy5jMC5jMS5wbHVzLmZpbmFsPC1zZXRkaWZmKHd0LmRlbGV0ZXJpb3VzLmRlbGV0aW9ucy5jMC5jMS5wbHVzLmhpZ2guY29uZmlkZW5jZSx3dC5iZW5lZmljaWFsLmRlbGV0aW9ucy5jMC5jMS5wbHVzLmhpZ2guY29uZmlkZW5jZSkKd3QuYmVuZWZpY2lhbC5kZWxldGlvbnMuYzAuYzEucGx1cy5maW5hbDwtc2V0ZGlmZih3dC5iZW5lZmljaWFsLmRlbGV0aW9ucy5jMC5jMS5wbHVzLmhpZ2guY29uZmlkZW5jZSx3dC5kZWxldGVyaW91cy5kZWxldGlvbnMuYzAuYzEucGx1cy5oaWdoLmNvbmZpZGVuY2UpCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKI3Byb2Nlc3MgQUxERXgyIG91dHB1dCBmb3IgV1QrVEVUIChUMikgdnMgV1QgKFQwKSAod3Qua28uaXFsci5jMC5jMi5wbHVzKQojaWRlbnRpZnkgdW5kZXItcmVwcmVzZW50ZWQgKGRlbGV0ZXJpb3VzKSBLTyBkZXNpZ25zCnd0LmRlbGV0ZXJpb3VzLmZlYXV0dXJlcy5jMC5jMi5wbHVzPC1yb3duYW1lcyh3dC5rby5pcWxyLmMwLmMyLnBsdXMpW3doaWNoKHd0LmtvLmlxbHIuYzAuYzIucGx1cyR3ZS5lQkggPCBxdmFsLnRocmVzaG9sZCAgJiB3dC5rby5pcWxyLmMwLmMyLnBsdXMkd2kuZUJIIDwgcXZhbC50aHJlc2hvbGQgICYgd3Qua28uaXFsci5jMC5jMi5wbHVzJGVmZmVjdCA8IC0xKmVmZmVjdC50aHJlc2hvbGQgKV0KI2lkZW50aWZ5IGdlbmVzIHdob3NlIGRlbGV0aW9ucyB3ZXJlIGRlbGV0ZXJpb3VzCnd0LmRlbGV0ZXJpb3VzLmRlbGV0aW9ucy5jMC5jMi5wbHVzLmhpZ2guY29uZmlkZW5jZTwtZGVmaW5lLmhpZ2guY29uZmluZGVuY2UuZ2VuZXMoZGVzaWduLnNldCA9d3QuZGVsZXRlcmlvdXMuZmVhdXR1cmVzLmMwLmMyLnBsdXMsIGFsZGV4Lm91dHB1dC5tYXRyaXggPSB3dC5rby5pcWxyLmMwLmMyLnBsdXMscmVhZC5jb3VudC5tYXRyaXggPSB3dC5rby5saWJyYXJ5LmNvdW50Lm1hdHJpeC53aXRoLmdlbmUuaW5mbykKI2lkZW50aWZ5IG92ZXItcmVwcmVzZW50ZWQgKGJlbmVmaWNpYWwpIEtPIGRlc2lnbnMKd3QuYmVuZWZpY2lhbC5mZWF1dHVyZXMuYzAuYzIucGx1czwtcm93bmFtZXMod3Qua28uaXFsci5jMC5jMi5wbHVzKVt3aGljaCh3dC5rby5pcWxyLmMwLmMyLnBsdXMkd2UuZUJIIDwgcXZhbC50aHJlc2hvbGQgICYgd3Qua28uaXFsci5jMC5jMi5wbHVzJHdpLmVCSCA8IHF2YWwudGhyZXNob2xkICAmIHd0LmtvLmlxbHIuYzAuYzIucGx1cyRlZmZlY3QgPiBlZmZlY3QudGhyZXNob2xkKV0KI2lkZW50aWZ5IGdlbmVzIHdob3NlIGRlbGV0aW9ucyB3ZXJlIGJlbmVmaWNpYWwKd3QuYmVuZWZpY2lhbC5kZWxldGlvbnMuYzAuYzIucGx1cy5oaWdoLmNvbmZpZGVuY2U8LWRlZmluZS5oaWdoLmNvbmZpbmRlbmNlLmdlbmVzKGRlc2lnbi5zZXQgPXd0LmJlbmVmaWNpYWwuZmVhdXR1cmVzLmMwLmMyLnBsdXMsIGFsZGV4Lm91dHB1dC5tYXRyaXggPSB3dC5rby5pcWxyLmMwLmMyLnBsdXMscmVhZC5jb3VudC5tYXRyaXggPSB3dC5rby5saWJyYXJ5LmNvdW50Lm1hdHJpeC53aXRoLmdlbmUuaW5mbykKI3JlbW92ZSBnZW5lcyB3aXRoIG11dGFudCBkZXNpZ25zIGlkZW50aWZpZWQgYXMgYm90aCBiZW5lZmljaWFsIEFORCBkZWxldGVyaW91cwp3dC5kZWxldGVyaW91cy5kZWxldGlvbnMuYzAuYzIucGx1cy5maW5hbDwtc2V0ZGlmZih3dC5kZWxldGVyaW91cy5kZWxldGlvbnMuYzAuYzIucGx1cy5oaWdoLmNvbmZpZGVuY2Usd3QuYmVuZWZpY2lhbC5kZWxldGlvbnMuYzAuYzIucGx1cy5oaWdoLmNvbmZpZGVuY2UpCnd0LmJlbmVmaWNpYWwuZGVsZXRpb25zLmMwLmMyLnBsdXMuZmluYWw8LXNldGRpZmYod3QuYmVuZWZpY2lhbC5kZWxldGlvbnMuYzAuYzIucGx1cy5oaWdoLmNvbmZpZGVuY2Usd3QuZGVsZXRlcmlvdXMuZGVsZXRpb25zLmMwLmMyLnBsdXMuaGlnaC5jb25maWRlbmNlKQojY29uc29saWRhdGUgcmVzdWx0cyBmb3IgdGhlIFdUIGxpYnJhcnkKd3QuZGVsZXRlcmlvdXMuYWxkZXguY29tcGlsYXRpb248LXVuaW9uKHd0LmRlbGV0ZXJpb3VzLmRlbGV0aW9ucy5jMC5jMS5wbHVzLmZpbmFsLHd0LmRlbGV0ZXJpb3VzLmRlbGV0aW9ucy5jMC5jMi5wbHVzLmZpbmFsKQp3dC5iZW5lZmljaWFsLmFsZGV4LmNvbXBpbGF0aW9uPC11bmlvbih3dC5iZW5lZmljaWFsLmRlbGV0aW9ucy5jMC5jMS5wbHVzLmZpbmFsLHd0LmJlbmVmaWNpYWwuZGVsZXRpb25zLmMwLmMyLnBsdXMuZmluYWwpCnByaW50KHBhc3RlKCJXVCBoYWQiLGxlbmd0aCh3dC5kZWxldGVyaW91cy5hbGRleC5jb21waWxhdGlvbiksImdlbmVzIHdob3NlIGRlbGV0aW9ucyB3ZXJlIGRlbGV0ZXJpb3VzIixzZXA9IiAiKSkKcHJpbnQocGFzdGUoIldUIGhhZCIsbGVuZ3RoKHd0LmJlbmVmaWNpYWwuYWxkZXguY29tcGlsYXRpb24pLCJnZW5lcyB3aG9zZSBkZWxldGlvbnMgd2VyZSBiZW5lZmljaWFsIixzZXA9IiAiKSkKYGBgCjMuNCBGaWcuIDNDCmBgYHtyfQojcGxvdCBwcm9maWxlcyBvZiBjaGFuZ2VzIGluIGFidW5kYW5jZSAod2l0aCByZXNwZWN0IHRvIFQwKSBmb3Igc2VsZWN0ZWQgZ2VuZXMgKG9uZSBLTyBkZXNpZ24gcGVyIGdlbmUpCnNlbGVjdGVkLmdlbmVzPC1jKCJhdHBBIiwiZnJkQyIsImFjcloiLCJtZHRBIiwidXZyQSIsImFyY0EiLCJwaG9QIiwicnBvUyIsImN5dFIiKQojY29ycmVzcG9uZGluZyBLTyBkZXNpZ25zIChpbiB0aGUgc2FtZSBvcmRlciBvZiB0aGUgc2VsZWN0ZWQgZ2VuZXMpCnNlbGVjdGVkLmRlc2lnbnM8LWMoIjY0MTc1NjAiLCI2NDE4OTE4IiwiNjQyMzE1NiIsIjY0MTc0NjEiLCI2NDIyNTU2IiwiNjQwNTk3MSIsIjY0MjEzMDQiLCI2NDE0NTQzIiwiNjQxNzI5MiIpCnBhcihtZnJvdz1jKDMsMykpCiNsb29wIHRvIGdlbmVyYXRlIGVhY2ggc3VicGFuZWwKZm9yKGkgaW4gMTpsZW5ndGgoc2VsZWN0ZWQuZ2VuZXMpKQogIHsKICAgIGN1cnJlbnQuZGVzaWduPC1zZWxlY3RlZC5kZXNpZ25zW2ldCiAgICBjdXJyZW50LmdlbmU8LXNlbGVjdGVkLmdlbmVzW2ldCiAgICAjcHJvZmlsZSBvZiBhYnVuZGFuY2UgZGlmZmVyZW5jZSBvZiBjdXJyZW50IGdlbmUgaW4gIGFudGliaW90aWMtZnJlZSBUZXRSIGxpYnJhcnkKICAgIHRldFIudW50cmVhdGVkLnZlY3RvcjwtYygwLHRldFIua28uaXFsci5jMC5jMS5taW51c1tjdXJyZW50LmRlc2lnbiwiZGlmZi5idHciXSx0ZXRSLmtvLmlxbHIuYzAuYzIubWludXNbY3VycmVudC5kZXNpZ24sImRpZmYuYnR3Il0pIAogICAgI3Byb2ZpbGUgb2YgYWJ1bmRhbmNlIGRpZmZlcmVuY2Ugb2YgY3VycmVudCBnZW5lIGluICB0ZXRyYWN5Y2xpbmUtdHJlYXRlZCBUZXRSIGxpYnJhcnkKICAgIHRldFIudHJlYXRlZC52ZWN0b3I8LWMoMCx0ZXRSLmtvLmlxbHIuYzAuYzEucGx1c1tjdXJyZW50LmRlc2lnbiwiZGlmZi5idHciXSx0ZXRSLmtvLmlxbHIuYzAuYzIucGx1c1tjdXJyZW50LmRlc2lnbiwiZGlmZi5idHciXSkKICAgICNwcm9maWxlIG9mIGFidW5kYW5jZSBkaWZmZXJlbmNlIG9mIGN1cnJlbnQgZ2VuZSBpbiAgYW50aWJpb3RpYy1mcmVlIFdUIGxpYnJhcnkKICAgIHd0LnVudHJlYXRlZC52ZWN0b3I8LWMoMCx3dC5rby5pcWxyLmMwLmMxLm1pbnVzW2N1cnJlbnQuZGVzaWduLCJkaWZmLmJ0dyJdLHd0LmtvLmlxbHIuYzAuYzIubWludXNbY3VycmVudC5kZXNpZ24sImRpZmYuYnR3Il0pCiAgICAjcHJvZmlsZSBvZiBhYnVuZGFuY2UgZGlmZmVyZW5jZSBvZiBjdXJyZW50IGdlbmUgaW4gIHRldHJhY3ljbGluZS10cmVhdGVkIFdUIGxpYnJhcnkKICAgIHd0LnRyZWF0ZWQudmVjdG9yPC1jKDAsd3Qua28uaXFsci5jMC5jMS5wbHVzW2N1cnJlbnQuZGVzaWduLCJkaWZmLmJ0dyJdLHd0LmtvLmlxbHIuYzAuYzIucGx1c1tjdXJyZW50LmRlc2lnbiwiZGlmZi5idHciXSkKICAgICNjcmVhdGUgcGxvdCBmb3IgY3VycmVudCBnZW5lCiAgICBwbG90KHk9dGV0Ui51bnRyZWF0ZWQudmVjdG9yLHg9MDoyLGNvbD0icmVkIixsdHk9Mix5bGltPXJhbmdlKGModGV0Ui51bnRyZWF0ZWQudmVjdG9yLHRldFIudHJlYXRlZC52ZWN0b3Isd3QudW50cmVhdGVkLnZlY3Rvcix3dC50cmVhdGVkLnZlY3RvciksbmEucm0gPSBUKSxtYWluPXBhc3RlKGN1cnJlbnQuZ2VuZSxjdXJyZW50LmRlc2lnbixzZXA9Ii0iKSx0eXBlPSJvIix5bGFiPWV4cHJlc3Npb24ocGFzdGUoRGVsdGEsImFidW5kYW5jZSAodnMgdDApIikpLHhsYWI9IkN5Y2xlIixjZXg9MS4xLGNleC5sYWI9MS4xLCBjZXguYXhpcz0xLjEpCiAgICBwb2ludHMoeT10ZXRSLnRyZWF0ZWQudmVjdG9yLHg9MDoyLGNvbD0icmVkNCIsdHlwZT0ibyIpCiAgICBwb2ludHMoeT13dC50cmVhdGVkLnZlY3Rvcix4PTA6Mixjb2w9ImJsdWU0Iix0eXBlPSJvIikKICAgIHBvaW50cyh5PXd0LnVudHJlYXRlZC52ZWN0b3IseD0wOjIsY29sPSJibHVlIix0eXBlPSJvIixsdHk9MikKICB9CmBgYAozLjUgRmlnLiBTNApgYGB7cn0KI2NyZWF0ZSBGaWcuIFM0QQojY29tcGFyZSBnZW5lcyB3aG9zZSBkZWxldGlvbiBhZmZlY3QgZml0bmVzcyBvbiBUZXRSIGFuZC9vciBXVCBiYWNrZ3JvdW5kcwojY29tcGFyaXNvbiBvZiBnZW5lcyBhc3NvY2lhdGVkIHdpdGggZGVsZXRlcmlvdXMgS08gZGVsZXRpb25zCmNvbnNlcnZlZC5kZWxldGVyaW91cy5nZW5lczwtaW50ZXJzZWN0KHd0LmRlbGV0ZXJpb3VzLmFsZGV4LmNvbXBpbGF0aW9uLHRldFIuZGVsZXRlcmlvdXMuYWxkZXguY29tcGlsYXRpb24pCnRldFIudW5pcXVlLmRlbGV0ZXJpb3VzLmdlbmVzPC1zZXRkaWZmKHRldFIuZGVsZXRlcmlvdXMuYWxkZXguY29tcGlsYXRpb24sd3QuZGVsZXRlcmlvdXMuYWxkZXguY29tcGlsYXRpb24pCnd0LnVuaXF1ZS5kZWxldGVyaW91cy5nZW5lczwtc2V0ZGlmZih3dC5kZWxldGVyaW91cy5hbGRleC5jb21waWxhdGlvbix0ZXRSLmRlbGV0ZXJpb3VzLmFsZGV4LmNvbXBpbGF0aW9uKQojY29tcGFyaXNvbiBvZiBnZW5lcyBhc3NvY2lhdGVkIHdpdGggYmVuZWZpY2lhbCBLTyBkZWxldGlvbnMKY29uc2VydmVkLmJlbmVmaWNpYWwuZ2VuZXM8LWludGVyc2VjdCh3dC5iZW5lZmljaWFsLmFsZGV4LmNvbXBpbGF0aW9uLHRldFIuYmVuZWZpY2lhbC5hbGRleC5jb21waWxhdGlvbikKdGV0Ui51bmlxdWUuYmVuZWZpY2lhbC5nZW5lczwtc2V0ZGlmZih0ZXRSLmJlbmVmaWNpYWwuYWxkZXguY29tcGlsYXRpb24sd3QuYmVuZWZpY2lhbC5hbGRleC5jb21waWxhdGlvbikKd3QudW5pcXVlLmJlbmVmaWNpYWwuZ2VuZXM8LXNldGRpZmYod3QuYmVuZWZpY2lhbC5hbGRleC5jb21waWxhdGlvbix0ZXRSLmJlbmVmaWNpYWwuYWxkZXguY29tcGlsYXRpb24pCiNjb21waWxlIG5hbWUgb2YgZ2VuZXMgdGhhdCBpbXBhY3QgZml0bmVzcyBpbiB0aGUgV1QgYW5kL29yIFRldFIgc3RyYWlucyBkdXJpbmcgdGV0cmFjeWNsaW5lIHRyZWF0bWVudApkaWZmZXJlbnRpYWxseS5hYnVuZGFudC5nZW5lLmNvbXBpbGF0aW9uPC11bmlxdWUoYyhjb25zZXJ2ZWQuYmVuZWZpY2lhbC5nZW5lcyx3dC51bmlxdWUuYmVuZWZpY2lhbC5nZW5lcyx0ZXRSLnVuaXF1ZS5iZW5lZmljaWFsLmdlbmVzLGNvbnNlcnZlZC5kZWxldGVyaW91cy5nZW5lcyx3dC51bmlxdWUuZGVsZXRlcmlvdXMuZ2VuZXMsdGV0Ui51bmlxdWUuZGVsZXRlcmlvdXMuZ2VuZXMpKQojY3JlYXRlIG1hdHJpeCBmb3IgaGVhdG1hcAppbnB1dC5tYXRyaXguZm9yLmhlYXRtYXA8LW1hdHJpeChucm93PWxlbmd0aChkaWZmZXJlbnRpYWxseS5hYnVuZGFudC5nZW5lLmNvbXBpbGF0aW9uKSxuY29sPTIsZGltbmFtZXMgPSBsaXN0KGRpZmZlcmVudGlhbGx5LmFidW5kYW50LmdlbmUuY29tcGlsYXRpb24sYygiV1QiLCJUZXRSIikpLDApCiNmaWxsIG91dCBpbnB1dCBtYXRyaXgKI3RoZSBub3RhdGlvbiBpczogKzEgPSBiZW5lZmljaWFsIGRlbGV0aW9uLCAtMSA9IGRlbGV0ZXJpb3VzIGRlbGV0aW9uLCAwID0gbmV1dHJhbApmb3IoZ2VuZSBpbiBkaWZmZXJlbnRpYWxseS5hYnVuZGFudC5nZW5lLmNvbXBpbGF0aW9uKQp7CiAgI2NoZWNrIGlmIGRlbGV0aW9uIG9mIGN1cnJlbnQgZ2VuZSBpcyBiZW5lZmljaWFsIGluIHRoZSBXVCBiYWNrZ3JvdW5kCiAgaWYoZ2VuZSAlaW4lIHd0LmJlbmVmaWNpYWwuYWxkZXguY29tcGlsYXRpb24pCiAgewogICAgaW5wdXQubWF0cml4LmZvci5oZWF0bWFwW2dlbmUsIldUIl08LTEKICB9CiAgI2NoZWNrIGlmIGRlbGV0aW9uIG9mIGN1cnJlbnQgZ2VuZSBpcyBkZWxldGVyaW91cyBpbiB0aGUgV1QgYmFja2dyb3VuZAogIGlmKGdlbmUgJWluJSB3dC5kZWxldGVyaW91cy5hbGRleC5jb21waWxhdGlvbikKICB7CiAgICBpbnB1dC5tYXRyaXguZm9yLmhlYXRtYXBbZ2VuZSwiV1QiXTwtIC0xCiAgfQogICNjaGVjayBpZiBkZWxldGlvbiBvZiBjdXJyZW50IGdlbmUgaXMgYmVuZWZpY2lhbCBpbiB0aGUgVGV0UiBiYWNrZ3JvdW5kCiAgaWYoZ2VuZSAlaW4lIHRldFIuYmVuZWZpY2lhbC5hbGRleC5jb21waWxhdGlvbikKICB7CiAgICBpbnB1dC5tYXRyaXguZm9yLmhlYXRtYXBbZ2VuZSwiVGV0UiJdPC0xCiAgfQogICNjaGVjayBpZiBkZWxldGlvbiBvZiBjdXJyZW50IGdlbmUgaXMgZGVsZXRlcmlvdXMgaW4gdGhlIFdUIGJhY2tncm91bmQKICBpZihnZW5lICVpbiUgdGV0Ui5kZWxldGVyaW91cy5hbGRleC5jb21waWxhdGlvbikKICB7CiAgICBpbnB1dC5tYXRyaXguZm9yLmhlYXRtYXBbZ2VuZSwiVGV0UiJdPC0gLTEKICB9Cn0KcGhlYXRtYXAoaW5wdXQubWF0cml4LmZvci5oZWF0bWFwLHNjYWxlPSJub25lIixjb2xvciA9IGNvbG9yUmFtcFBhbGV0dGUocmV2KGJyZXdlci5wYWwoMywgIlBpWUciKSkgKSgzKVszOjFdLGNsdXN0ZXJfcm93cz1GLGNsdXN0ZXJfY29scyA9IEYsZm9udHNpemUgPSA1LGFuZ2xlX2NvbCA9IDkwLGxlZ2VuZD1ULCBtYWluPSJGaWcuIFM0QSIsYnJlYWtzID1jKC0xLC0wLjAwMDEsMC4wMDAxLDEpLGxlZ2VuZF9icmVha3MgPSBjKC0xLC0wLjAwMDEsMC4wMDAxLDEpLGxlZ2VuZF9sYWJlbHMgPSBjKCItMSIsIjAiLCIwIiwiKzEiKSxzaG93X3Jvd25hbWVzPUZBTFNFKQojY3JlYXRlIEZpZy4gUzRCIAojd3JpdGUgQ1NWIGZpbGVzIHdpdGggVGV0Ui1zcGVjaWZpYyBkZWxldGVyaW91cyBhbmQgYmVuZWZpY2lhbCBnZW5lIGRlbGV0aW9ucwojd3JpdGUuY3N2KGZpbGU9Ii4uL0RhdGEvS09fbGlicmFyeV9jb21wZXRpdGlvbi9wcm9jZXNzZWRfY291bnRfZGF0YS90ZXRSX3NwZWNpZmljX2JlbmVmaWNpYWxfZ2VuZXNfMDgyNDIyLmNzdiIsY2JpbmQodHJhbnNsYXRlLmdlbmUubmFtZS50by5sb2N1cyh0ZXRSLnVuaXF1ZS5iZW5lZmljaWFsLmdlbmVzKSx0ZXRSLnVuaXF1ZS5iZW5lZmljaWFsLmdlbmVzKSkKI3dyaXRlLmNzdihmaWxlPSIuLi9EYXRhL0tPX2xpYnJhcnlfY29tcGV0aXRpb24vcHJvY2Vzc2VkX2NvdW50X2RhdGEvdGV0Ul9zcGVjaWZpY19kZWxldGVyaW91c19nZW5lc18wODI0MjIuY3N2IixjYmluZCh0cmFuc2xhdGUuZ2VuZS5uYW1lLnRvLmxvY3VzKHRldFIudW5pcXVlLmRlbGV0ZXJpb3VzLmdlbmVzKSx0ZXRSLnVuaXF1ZS5kZWxldGVyaW91cy5nZW5lcykpCiNiYXNlZCBvbiBvdXRwdXQgZnJvbSBEQVZJRCBmdW5jdGlvbmFsIGVucmljaG1lbnQgYW5hbHlzaXMKI2NyZWF0ZSBiYXJwbG90IApwYXIobWZyb3c9YygxLDIpKQpwbG90Lm5ldygpCmJhcnBsb3QoYyg0MCwyOSwxMyw2LDkpLGNleC5sYWI9MS4xLGNleC5heGlzPTEuMSxjZXgubmFtZXMgPSAxLjEseGxhYj0iTnVtYmVyIG9mIGdlbmVzIiwKbmFtZXM9YygiRmUvb3RoZXIgaW9uIHRyYW5zcG9ydCIsIlBpbHVzLWNlbGwgYWRoZXNpb24iLCJUQ0EiLCJFbnRlcm9iYWN0aW4gYmlvc3ludGhlc2lzIiwiVWJpcXVpbm9uZS9vdGhlciB0ZXJwZW5vaWQtcXVpbm9uZSBiaW9zeW50aGVzaXMiKSxjb2w9YygiIzY2YzJhNSIsIiNmYzhkNjIiLCIjOGRhMGNiIiwiI2U3OGFjMyIsIiNhNmQ4NTQiKSxsYXM9Mixob3JpeiA9IFQseGxpbT1jKDAsNDIpLG1haW49IkZpZy4gUzRCIikKI2NyZWF0ZSBGaWcuIFM0QwojaGVhdG1hcCBmb3IgVEZzIHdob3NlIGRlbGV0aW9uIGFmZmVjdCBmaXRuZXNzIG9mIFRldFIgYW5kL29yIFdUCiNkZWZpbmUgbmFtZXMgb2YgRS4gY29saSBURnMgCmVjb2xpLnRmczwtY29udmVydC5sb2N1cy50by5nZW5lLm5hbWUodGYubmFtZXMpCiNtYW51YWxseSB1cGRhdGUgVEYgbmFtZXMgdG8gaW5jbHVkZSBnZW5lIG5hbWUgc3lub255bSB1c2VkIGJ5IEluc2NyaXB0YVJlc29sdmVyCmVjb2xpLnRmc1t3aGljaChlY29saS50ZnM9PSJycGlSIildPC0iYWxzUiIKZWNvbGkudGZzW3doaWNoKGVjb2xpLnRmcz09InljZ0UiKV08LSJibHVSIgplY29saS50ZnNbd2hpY2goZWNvbGkudGZzPT0ieWNmUSIpXTwtImNvbVIiCmVjb2xpLnRmc1t3aGljaChlY29saS50ZnM9PSJmcnVSIildPC0iY3JhIgplY29saS50ZnNbd2hpY2goZWNvbGkudGZzPT0ieWZoQSIpXTwtImdsclIiCmVjb2xpLnRmc1t3aGljaChlY29saS50ZnM9PSJ5amlFIildPC0iaHlwVCIKZWNvbGkudGZzW3doaWNoKGVjb2xpLnRmcz09Im1hdEEiKV08LSJlY3BSIgplY29saS50ZnNbd2hpY2goZWNvbGkudGZzPT0iY2hwUiIpXTwtIm1hekUiCmVjb2xpLnRmc1t3aGljaChlY29saS50ZnM9PSJkZ3NBIildPC0ibWxjIgplY29saS50ZnNbd2hpY2goZWNvbGkudGZzPT0ieWdpVCIpXTwtIm1xc0EiCmVjb2xpLnRmc1t3aGljaChlY29saS50ZnM9PSJ5ZmVUIildPC0ibXVyUiIKZWNvbGkudGZzW3doaWNoKGVjb2xpLnRmcz09InljaloiKV08LSJwZ3JSIgplY29saS50ZnNbd2hpY2goZWNvbGkudGZzPT0ieWJqSyIpXTwtInJjZEEiCmVjb2xpLnRmc1t3aGljaChlY29saS50ZnM9PSJ5ZGNOIildPC0ic3V0UiIKZWNvbGkudGZzW3doaWNoKGVjb2xpLnRmcz09InllaFQiKV08LSJidHNSIgplY29saS50ZnNbd2hpY2goZWNvbGkudGZzPT0ieXFqSSIpXTwtIm5mZVIiCiNpZGVudGlmeSBURnMgd2hvc2UgZGVsZXRpb24gYWZmZWN0IGZpdG5lc3Mgb2YgVGV0UiBhbmQvb3IgV1QKZGlmZmVyZW50aWFsbHkuYWJ1bmRhbnQudGZzPC1pbnRlcnNlY3QoZWNvbGkudGZzLGRpZmZlcmVudGlhbGx5LmFidW5kYW50LmdlbmUuY29tcGlsYXRpb24pCiNjcmVhdGUgbWF0cml4IHdpdGggY2hhbmdlcyBpbiBhYnVuZGFuY2UgKGRlbHRhKSB3aXRoIHJlc3BlY3QgdG8gVDAgZm9yIHNlbGVjdGVkIFRGcyBkdXJpbmcgdGV0cmFjeWNsaW5lIHRyZWF0bWVudAp0Zi5kZWxldGlvbi5kZWx0YS5hYnVuZGFuY2UubWF0cml4PC1jKCkKI3ZlY3RvciB0byByZWNvcmQgb3JkZXIgb2YgVEZzIChpbXBvcnRhbnQgZm9yIG5leHQgc3RlcCkKb3JkZXIub2YudGZzLmluLm1hdHJpeDwtYygpCiNpZGVudGlmeSBLTyBkZXNpZ25zIGFzc29jaWF0ZWQgd2l0aCBkaWZmZXJlbnRpYWxseSBhYnVuZGFudCBURnMKdGYua28uZGVzaWduczwtcm93bmFtZXModGV0Ui5rby5saWJyYXJ5LmNvdW50Lm1hdHJpeC53aXRoLmdlbmUuaW5mbylbd2hpY2godGV0Ui5rby5saWJyYXJ5LmNvdW50Lm1hdHJpeC53aXRoLmdlbmUuaW5mb1ssImdlbmUiXSVpbiUgZGlmZmVyZW50aWFsbHkuYWJ1bmRhbnQudGZzKV0KI2ZpbGwgb3V0IHRmLmRlbGV0aW9uLmRlbHRhLmFidW5kYW5jZS5tYXRyaXgKZm9yKGQgaW4gdGYua28uZGVzaWducykKewogICAgY3VycmVudC5kZXNpZ24uZGVsdGEuYWJ1bmRhbmNlLnByb2ZpbGU8LWNiaW5kKHd0LmtvLmlxbHIuYzAuYzEucGx1c1tkLCJkaWZmLmJ0dyJdLHd0LmtvLmlxbHIuYzAuYzIucGx1c1tkLCJkaWZmLmJ0dyJdLHRldFIua28uaXFsci5jMC5jMS5wbHVzW2QsImRpZmYuYnR3Il0sdGV0Ui5rby5pcWxyLmMwLmMyLnBsdXNbZCwiZGlmZi5idHciXSkKICAgIHRmLmRlbGV0aW9uLmRlbHRhLmFidW5kYW5jZS5tYXRyaXg8LXJiaW5kKHRmLmRlbGV0aW9uLmRlbHRhLmFidW5kYW5jZS5tYXRyaXgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50LmRlc2lnbi5kZWx0YS5hYnVuZGFuY2UucHJvZmlsZSkKICAgIG9yZGVyLm9mLnRmcy5pbi5tYXRyaXg8LWMob3JkZXIub2YudGZzLmluLm1hdHJpeCx0ZXRSLmtvLmxpYnJhcnkuY291bnQubWF0cml4LndpdGguZ2VuZS5pbmZvW2QsImdlbmUiXSkKfQojcmVuYW1lIG1hdHJpeCB1c2luZyBURiBuYW1lcwpyb3duYW1lcyh0Zi5kZWxldGlvbi5kZWx0YS5hYnVuZGFuY2UubWF0cml4KTwtb3JkZXIub2YudGZzLmluLm1hdHJpeAojcmUtb3JkZXIgbWF0cml4IHJvd3MgYnkgVEYgbmFtZXMKdGYuZGVsZXRpb24uZGVsdGEuYWJ1bmRhbmNlLm1hdHJpeDwtdGYuZGVsZXRpb24uZGVsdGEuYWJ1bmRhbmNlLm1hdHJpeFtvcmRlcihyb3duYW1lcyh0Zi5kZWxldGlvbi5kZWx0YS5hYnVuZGFuY2UubWF0cml4KSksXQojY29tcHV0ZSBtZWFuIGRpZmZlcmVuY2UgaW4gYWJ1bmRhbmNlIGZvciBURnMgd2l0aCB0d28gS08gZGVzaWducwphdmVyYWdlLnRmLmRlbGV0aW9uLmRlbHRhLmFidW5kYW5jZS5tYXRyaXg8LWMoKQpmb3IodGYgaW4gdW5pcXVlKHJvd25hbWVzKHRmLmRlbGV0aW9uLmRlbHRhLmFidW5kYW5jZS5tYXRyaXgpKSkKewogIGN1cnJlbnQudGYucG9zaXRpb248LXdoaWNoKHJvd25hbWVzKHRmLmRlbGV0aW9uLmRlbHRhLmFidW5kYW5jZS5tYXRyaXgpPT10ZikKICBpZihsZW5ndGgoY3VycmVudC50Zi5wb3NpdGlvbik9PTIpCiAgewogICAgYXZlcmFnZS50Zi5kZWxldGlvbi5kZWx0YS5hYnVuZGFuY2UubWF0cml4PC1yYmluZChhdmVyYWdlLnRmLmRlbGV0aW9uLmRlbHRhLmFidW5kYW5jZS5tYXRyaXgsY29sTWVhbnModGYuZGVsZXRpb24uZGVsdGEuYWJ1bmRhbmNlLm1hdHJpeFtjdXJyZW50LnRmLnBvc2l0aW9uLF0sbmEucm0gPSBUKSkKICB9CiAgZWxzZQogIHsKICAgIGF2ZXJhZ2UudGYuZGVsZXRpb24uZGVsdGEuYWJ1bmRhbmNlLm1hdHJpeDwtcmJpbmQoYXZlcmFnZS50Zi5kZWxldGlvbi5kZWx0YS5hYnVuZGFuY2UubWF0cml4LHRmLmRlbGV0aW9uLmRlbHRhLmFidW5kYW5jZS5tYXRyaXhbY3VycmVudC50Zi5wb3NpdGlvbixdKQogIH0KfQpyb3duYW1lcyhhdmVyYWdlLnRmLmRlbGV0aW9uLmRlbHRhLmFidW5kYW5jZS5tYXRyaXgpPC11bmlxdWUocm93bmFtZXModGYuZGVsZXRpb24uZGVsdGEuYWJ1bmRhbmNlLm1hdHJpeCkpCiNyZXBsYWNlIE5BcyAodGhhdCBvY2N1ciBmb3IgdGhvc2UgdGltZSBwb2ludHMgaW4gd2hpY2ggYSBnZW5lIEtPcyB3ZXJlIG5vdCBkZXRlY3RlZCkgd2l0aCBhICIyMCIgdmFsdWUKYXZlcmFnZS50Zi5kZWxldGlvbi5kZWx0YS5hYnVuZGFuY2UubWF0cml4W3doaWNoKGlzLm5hKGF2ZXJhZ2UudGYuZGVsZXRpb24uZGVsdGEuYWJ1bmRhbmNlLm1hdHJpeCkpXTwtMjAKI2FkZCBjb2x1bW4gbmFtZXMKY29sbmFtZXMoYXZlcmFnZS50Zi5kZWxldGlvbi5kZWx0YS5hYnVuZGFuY2UubWF0cml4KTwtYygiV1QudDEiLCJXVC50MiIsIlRldFIudDEiLCJUZXRSLnQyIikKI2RlZmluZSBoZWF0bWFwIGJyZWFrcwpoZWF0bWFwLmJyZWFrczwtYygtMTAsLTQsLTIsLTEsLTAuNSwwLDAuNSwxLDIsNCwxMCwyMCkKI2dlbmVyYXRlIGhlYXRtYXAKcGhlYXRtYXAoYXZlcmFnZS50Zi5kZWxldGlvbi5kZWx0YS5hYnVuZGFuY2UubWF0cml4LHNjYWxlPSJub25lIixjb2xvciA9Yyhjb2xvclJhbXBQYWxldHRlKHJldihicmV3ZXIucGFsKDEwLCAiUGlZRyIpKSApKDEwKVsxMDoxXSwiYmxhY2siKSwKICAgICAgICAgY2x1c3Rlcl9yb3dzPUYsY2x1c3Rlcl9jb2xzID0gRixmb250c2l6ZSA9IDUsYW5nbGVfY29sID0gOTAsCmxlZ2VuZD1ULGJyZWFrcyA9aGVhdG1hcC5icmVha3MsbGVnZW5kX2JyZWFrcyA9IGhlYXRtYXAuYnJlYWtzLG1haW49IkZpZy4gUzRDIikKYGBgCjMuNiBGaWcuIFM1CmBgYHtyfQojcGxvdCBwcm9maWxlcyBvZiBjaGFuZ2VzIGluIGFidW5kYW5jZSAod2l0aCByZXNwZWN0IHRvIFQwKSBmb3Igc2VsZWN0ZWQgZ2VuZXMgKG9uZSBLTyBkZXNpZ24gcGVyIGdlbmUpCnNlbGVjdGVkLmdlbmVzPC1jKCJtZW5CIiwiZnJkQiIsImh5YkIiLCJtZGgiKQojY29ycmVzcG9uZGluZyBLTyBkZXNpZ25zIChpbiB0aGUgc2FtZSBvcmRlciBvZiB0aGUgc2VsZWN0ZWQgZ2VuZXMpCnNlbGVjdGVkLmRlc2lnbnM8LWMoIjY0MTkzMTciLCI2NDE2NzAyIiwiNjQxODI5MiIsIjY0MTkwOTEiKQojbG9vcCB0byBnZW5lcmF0ZSBlYWNoIHN1YnBhbmVsCnBhcihtZnJvdz1jKDIsMikpCmZvcihpIGluIDE6bGVuZ3RoKHNlbGVjdGVkLmdlbmVzKSkKewogIGN1cnJlbnQuZ2VuZTwtc2VsZWN0ZWQuZ2VuZXNbaV0KICBjdXJyZW50LmRlc2lnbjwtc2VsZWN0ZWQuZGVzaWduc1tpXQogICNwcm9maWxlIG9mIGFidW5kYW5jZSBkaWZmZXJlbmNlIG9mIGN1cnJlbnQgZ2VuZSBpbiAgYW50aWJpb3RpYy1mcmVlIFRldFIgbGlicmFyeQogIHRldFIudW50cmVhdGVkLnZlY3RvcjwtYygwLHRldFIua28uaXFsci5jMC5jMS5taW51c1tjdXJyZW50LmRlc2lnbiwiZGlmZi5idHciXSx0ZXRSLmtvLmlxbHIuYzAuYzIubWludXNbY3VycmVudC5kZXNpZ24sImRpZmYuYnR3Il0pCiAgI3Byb2ZpbGUgb2YgYWJ1bmRhbmNlIGRpZmZlcmVuY2Ugb2YgY3VycmVudCBnZW5lIGluICB0ZXRyYWN5Y2xpbmUtdHJlYXRlZCBUZXRSIGxpYnJhcnkKICB0ZXRSLnRldHJhY3ljbGluZS50cmVhdGVkLnZlY3RvcjwtYygwLHRldFIua28uaXFsci5jMC5jMS5wbHVzW2N1cnJlbnQuZGVzaWduLCJkaWZmLmJ0dyJdLHRldFIua28uaXFsci5jMC5jMi5wbHVzW2N1cnJlbnQuZGVzaWduLCJkaWZmLmJ0dyJdKQogICNwcm9maWxlIG9mIGFidW5kYW5jZSBkaWZmZXJlbmNlIG9mIGN1cnJlbnQgZ2VuZSBpbiAgYW50aWJpb3RpYy1mcmVlIFdUIGxpYnJhcnkKICB3dC51bnRyZWF0ZWQudmVjdG9yPC1jKDAsd3Qua28uaXFsci5jMC5jMS5taW51c1tjdXJyZW50LmRlc2lnbiwiZGlmZi5idHciXSx3dC5rby5pcWxyLmMwLmMyLm1pbnVzW2N1cnJlbnQuZGVzaWduLCJkaWZmLmJ0dyJdKQogICNwcm9maWxlIG9mIGFidW5kYW5jZSBkaWZmZXJlbmNlIG9mIGN1cnJlbnQgZ2VuZSBpbiAgdGV0cmFjeWNsaW5lLXRyZWF0ZWQgV1QgbGlicmFyeQogIHd0LnRldHJhY3ljbGluZS50cmVhdGVkLnZlY3RvcjwtYygwLHd0LmtvLmlxbHIuYzAuYzEucGx1c1tjdXJyZW50LmRlc2lnbiwiZGlmZi5idHciXSx3dC5rby5pcWxyLmMwLmMyLnBsdXNbY3VycmVudC5kZXNpZ24sImRpZmYuYnR3Il0pCiAgI2NyZWF0ZSBwbG90IGZvciBjdXJyZW50IGdlbmUKICBwbG90KHk9dGV0Ui51bnRyZWF0ZWQudmVjdG9yLHg9MDoyLGNvbD0icmVkIixsdHk9Mix5bGltPXJhbmdlKGModGV0Ui51bnRyZWF0ZWQudmVjdG9yLHRldFIudGV0cmFjeWNsaW5lLnRyZWF0ZWQudmVjdG9yLHd0LnVudHJlYXRlZC52ZWN0b3Isd3QudGV0cmFjeWNsaW5lLnRyZWF0ZWQudmVjdG9yKSxuYS5ybSA9IFQpLG1haW49cGFzdGUoY3VycmVudC5nZW5lLGN1cnJlbnQuZGVzaWduLHNlcD0iLSIpLHR5cGU9Im8iLHlsYWI9ZXhwcmVzc2lvbihwYXN0ZShEZWx0YSwiYWJ1bmRhbmNlICh2cyB0MCkiKSkseGxhYj0iQ3ljbGUiLGNleD0xLjEsY2V4LmxhYj0xLjEsIGNleC5heGlzPTEuMSkKICBwb2ludHMoeT10ZXRSLnRldHJhY3ljbGluZS50cmVhdGVkLnZlY3Rvcix4PTA6Mixjb2w9InJlZDQiLHR5cGU9Im8iKQogIHBvaW50cyh5PXd0LnVudHJlYXRlZC52ZWN0b3IseD0wOjIsY29sPSJibHVlIix0eXBlPSJvIixsdHk9MikKICBwb2ludHMoeT13dC50ZXRyYWN5Y2xpbmUudHJlYXRlZC52ZWN0b3IseD0wOjIsY29sPSJibHVlNCIsdHlwZT0ibyIpCn0KYGBgCjMuNyBFdmFsdWF0ZSBvdmVybGFwIGJldHdlZW4gVGV0UiBkcm9wb3V0cyBhdCBUMyBhbmQgQUxERXgyIHJlc3VsdHMKYGBge3J9CiNpZGVudGlmeSBnZW5lcyBsYWJlbGVkIGFzIHVuZGV0ZWN0YWJsZSBhdCB0aGUgZW5kIG9mIHRoZSBleHBlcmltZW50IHdpdGggdGV0cmFjeWNsaW5lCiNleGNsdWRlIGdlbmVzIHRoYXQgd2VyZSBub3QgZGV0ZWN0ZWQgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgZXhwZXJpbWVudCAoVDApIGFuZCB0aGUgZW5kIG9mIHRoZSBleHBlcmltZW50IHdpdGggbm8gdGV0cmFjeWNsaW5lIChUMy1URVQpCnRldFIuZGVwbGV0ZWQuZ2VuZXMuZHVlLnRvLnRldHJhY3ljbGluZTwtc2V0ZGlmZih0ZXRSLmRlcGxldGVkLmdlbmVzW1siVDMoKykiXV0sdW5pb24odGV0Ui5kZXBsZXRlZC5nZW5lc1tbIlQwIl1dLHRldFIuZGVwbGV0ZWQuZ2VuZXNbWyJUMygtKSJdXSkpCiNvdmVybGFwIHdpdGggVGV0Ui1zcGVjaWZpYyBnZW5lcyB3aXRoIGRlbGV0ZXJpb3VzIGRlbGV0aW9ucwpvdmVybGFwcGluZy5nZW5lczwtaW50ZXJzZWN0KHRldFIuZGVwbGV0ZWQuZ2VuZXMuZHVlLnRvLnRldHJhY3ljbGluZSx0ZXRSLnVuaXF1ZS5kZWxldGVyaW91cy5nZW5lcykKcHJpbnQocGFzdGUoIlRoZXJlIGFyZSIsbGVuZ3RoKG92ZXJsYXBwaW5nLmdlbmVzKSwiZ2VuZXMgaW4gY29tbW9uIixzZXA9IiAiKSkKI3BlcmZvcm0gaHlwZXJnZW9tZXRyaWMgdGVzdAojZGVmaW5lIGdlbmUgdW5pdmVyc2UuIEZpcnN0LCB3ZSBuZWVkIHRvIGlkZW50aWZ5IHdoaWNoIGdlbmVzIHdlcmUgaW5jbHVkZWQgaW4gdGhlIEFMREV4MiBjb21wYXJpc29ucyBmb3IgVDEoK1RFVCkgdnMgVDAgYW5kIFQyKCtURVQpIHZzIFQwCmFsZGV4Mi5kZXNpZ25zLmluY2x1ZGVkLmluLmNvbXBhcmlzb25zPC11bmlvbihyb3duYW1lcyh0ZXRSLmtvLmlxbHIuYzAuYzEucGx1cykscm93bmFtZXModGV0Ui5rby5pcWxyLmMwLmMyLnBsdXMpKQojcmVtb3ZlIHR3byBjb250cm9sIEtPIGRlc2lnbnMgbm90IGFzc29jaWF0ZWQgd2l0aCBhbnkgZ2VuZQphbGRleDIuZGVzaWducy5pbmNsdWRlZC5pbi5jb21wYXJpc29uczwtc2V0ZGlmZihhbGRleDIuZGVzaWducy5pbmNsdWRlZC5pbi5jb21wYXJpc29ucyxjKCI1MDA5NTU2NTMiLCI1MDA5NTU2NTQiKSkKI2RlZmluZSB0aGUgZ2VuZXMgYXNzb2NpYXRlZCB3aXRoIHRoZSBLTyBkZXNpZ25zCmdlbmUudW5pdmVyc2UuZm9yLnRlc3Q8LXVuaXF1ZSh0ZXRSLmtvLmxpYnJhcnkuY291bnQubWF0cml4LndpdGguZ2VuZS5pbmZvW2FsZGV4Mi5kZXNpZ25zLmluY2x1ZGVkLmluLmNvbXBhcmlzb25zLCJnZW5lIl0pCiNydW4gaHlwZXJnZW9tZXRyaWMgdGVzdApxPC1sZW5ndGgob3ZlcmxhcHBpbmcuZ2VuZXMpCm08LWxlbmd0aChpbnRlcnNlY3QoZ2VuZS51bml2ZXJzZS5mb3IudGVzdCx0ZXRSLmRlcGxldGVkLmdlbmVzLmR1ZS50by50ZXRyYWN5Y2xpbmUpKQpuPC1sZW5ndGgoZ2VuZS51bml2ZXJzZS5mb3IudGVzdCktbQprPC1sZW5ndGgoaW50ZXJzZWN0KHRldFIudW5pcXVlLmRlbGV0ZXJpb3VzLmdlbmVzLGdlbmUudW5pdmVyc2UuZm9yLnRlc3QpKQpwdmFsdWUub3ZlcmxhcDwtcGh5cGVyKHEtMSxtLG4sayxsb3dlci50YWlsID0gRikKcHJpbnQocGFzdGUoIk92ZXJsYXAgUC12YWx1ZToiLHJvdW5kKHB2YWx1ZS5vdmVybGFwLGRpZ2l0cz0zKSxzZXA9IiAiKSkKYGBgCjMuOCBDcmVhdGUgaW5kaXZpZHVhbCB0YWJsZXMgZm9yIERhdGEgU2V0IFMyICh3aXRoIGluZm9ybWF0aW9uIGFib3V0IHVuZGV0ZWN0YWJsZSBnZW5lcykKYGBge3J9CiNhbHRlcm5hdGl2ZSBmdW5jdGlvbiB0byBjb252ZXJ0IGdlbmUgbmFtZXMgaW50byBjb3JyZXNwb25kaW5nIGxvY2kKI3RoaXMgZnVuY3Rpb24gdXNlcyBFLiBjb2xpIGdlbm9tZSBhbm5vdGF0aW9uIHRvIGV4dHJhY3QgbG9jdXMgdGFnCmNvbnZlcnQuZ2VuZS5uYW1lLnRvLmxvY3VzLnRhZzwtZnVuY3Rpb24oZ2VuZU5hbWVzKQp7CiAgb3V0cHV0PC1jKCkKICAjcmVhZCBFLiBjb2xpIGdlbm9tZSBpbmZvcm1hdGlvbgogIGVjb2xpLmdlbm9tZTwtcmVhZC5jc3YoIi4uL0RhdGEvTWlzY2VsbGFuZW91c19maWxlcy9lY29saV9nZW5lX2lkcy5jc3YiLGhlYWRlcj1UKQogICNkZWZpbmUgbG9jdXMgdGFnIGZvciBlYWNoIGdlbmUgb2YgdGhlIGlucHV0IHNldAogIGZvcihnIGluIGdlbmVOYW1lcykKICB7CiAgICAjZmlyc3QsIGV2YWx1YXRlIGlmIHRoZSBjdXJyZW50IG5hbWUgaXMgdGhlIHN0YW5kYXJkIGdlbmUgc3ltYm9sCiAgICBjdXJyZW50LmdlbmUucG9zaXRpb248LXdoaWNoKGVjb2xpLmdlbm9tZSRTeW1ib2wgPT0gZykKICAgICNzZWNvbmQsIGV2YWx1YXRlIGlmIHRoZSBjdXJyZW50IG5hbWUgaXMgYSBzeW5vbnltIAogICAgY3VycmVudC5nZW5lLmFsdGVybmF0aXZlLnBvc2l0aW9uPC1ncmVwKGcsZWNvbGkuZ2Vub21lJEFsaWFzZXMpCiAgICAjZm9yIHRoZSBmaXN0IGNhc2UsIGV4dHJhY3QgbG9jdXMgaWQgCiAgICBpZihsZW5ndGgoY3VycmVudC5nZW5lLnBvc2l0aW9uKT09MSkKICAgIHsKICAgICAgb3V0cHV0PC1jKG91dHB1dCxzdHJzcGxpdChlY29saS5nZW5vbWUkQWxpYXNlc1tjdXJyZW50LmdlbmUucG9zaXRpb25dLHNwbGl0ID0gIiwiKVtbMV1dWzFdKQogICAgfQogICAgI2luIHRoZSBzZWNvbmQgc2NlbmFyaW8KICAgIGlmKGxlbmd0aChjdXJyZW50LmdlbmUucG9zaXRpb24pPT0wKSAKICAgIHsKICAgICAgI2V4dHJhY3QgdGhlIGxvY3VzIGlkCiAgICAgIGlmKGxlbmd0aChjdXJyZW50LmdlbmUuYWx0ZXJuYXRpdmUucG9zaXRpb24pPT0xKQogICAgICB7CiAgICAgICAgb3V0cHV0PC1jKG91dHB1dCxzdHJzcGxpdChlY29saS5nZW5vbWUkQWxpYXNlc1tjdXJyZW50LmdlbmUuYWx0ZXJuYXRpdmUucG9zaXRpb25dLHNwbGl0ID0gIiwiKVtbMV1dWzFdKQogICAgICB9CiAgICAjaWYgdGhlIGN1cnJlbnQgbmFtZSB3YXMgbm90IGZvdW5kIG9yIG1vcmUgdGhhbiBvbmUgcG90ZW50aWFsIGxvY2kgd2VyZSBpZGVudGlmaWVkLCBrZWVwIHRoZSBvcmlnaW5hbCBnZW5lIG5hbWUgICAKICAgIGlmKGxlbmd0aChjdXJyZW50LmdlbmUuYWx0ZXJuYXRpdmUucG9zaXRpb24pIT0xKQogICAgewogICAgICBvdXRwdXQ8LWMob3V0cHV0LGcpCiAgICB9CiAgICB9CiAgfQogIG91dHB1dAp9CiN3cml0ZSBDU1YgZmlsZXMgd2l0aCBnZW5lcyBkZXBsZXRlZCBhbG9uZyB0aGUgVGV0UiBleHBlcmltZW50CmZvcihpIGluIDE6NykKewogICNjcmVhdGUgdGFibGUgd2l0aCBuYW1lIG9mIGRlcGxldGVkIGdlbmVzIGFuZCB0aGUgY29ycmVzcG9uZGluZyBsb2NpCiAgdGVtcG9yYWwudGFibGU8LWNiaW5kKHRldFIuZGVwbGV0ZWQuZ2VuZXNbW2ldXSxjb252ZXJ0LmdlbmUubmFtZS50by5sb2N1cy50YWcodGV0Ui5kZXBsZXRlZC5nZW5lc1tbaV1dKSkKICBjb2xuYW1lcyh0ZW1wb3JhbC50YWJsZSk8LWMoIkdlbmUgTmFtZSIsIkxvY3VzIikKICB3cml0ZS5jc3YoZmlsZT1wYXN0ZSgiLi4vLi4vU3VwcGxlbWVudC9EYXRhc2V0IFMyL1RldFJfIixuYW1lcyh0ZXRSLmRlcGxldGVkLmdlbmVzKVtpXSwiX2RlcGxldGVkX2dlbmVzLmNzdiIsc2VwPSIiKSx0ZW1wb3JhbC50YWJsZSxxdW90ZSA9IEYscm93Lm5hbWVzID0gRikKfQojd3JpdGUgQ1NWIGZpbGUgd2l0aCBpbmZvcm1hdGlvbiBhYm91dCBvdmVybGFwIGJldHdlZW4gdGltZSBwb2ludHMKdGV0Ui5kZXBsZXRlZC5nZW5lcy5jb21wYXJpc29uLnRhYmxlPC1tYXRyaXgobnJvdz03LG5jb2w9NyxkaW1uYW1lcz1saXN0KG5hbWVzKHRldFIuZGVwbGV0ZWQuZ2VuZXMpLG5hbWVzKHRldFIuZGVwbGV0ZWQuZ2VuZXMpKSwwKQpmb3IociBpbiAxOjcpCnsKICBmb3IoYyBpbiAxOjcpCiAgewogICAgdGV0Ui5kZXBsZXRlZC5nZW5lcy5jb21wYXJpc29uLnRhYmxlW3IsY108LWxlbmd0aChpbnRlcnNlY3QodGV0Ui5kZXBsZXRlZC5nZW5lc1tbcl1dLHRldFIuZGVwbGV0ZWQuZ2VuZXNbW2NdXSkpCiAgfQp9CiB3cml0ZS5jc3YoZmlsZT0iLi4vLi4vU3VwcGxlbWVudC9EYXRhc2V0IFMyL1RldFJfZ2VuZV9kZXBsZXRpb25fY29tcGFyaXNvbi5jc3YiLHRldFIuZGVwbGV0ZWQuZ2VuZXMuY29tcGFyaXNvbi50YWJsZSkKI3dyaXRlIENTViBmaWxlcyB3aXRoIGdlbmVzIGRlcGxldGVkIGluIHRoZSBXVCBleHBlcmltZW50cwpmb3IoaSBpbiAxOjcpCnsKICB0ZW1wb3JhbC50YWJsZTwtY2JpbmQod3QuZGVwbGV0ZWQuZ2VuZXNbW2ldXSxjb252ZXJ0LmdlbmUubmFtZS50by5sb2N1cy50YWcod3QuZGVwbGV0ZWQuZ2VuZXNbW2ldXSkpCiAgY29sbmFtZXModGVtcG9yYWwudGFibGUpPC1jKCJHZW5lIE5hbWUiLCJMb2N1cyIpCiAgd3JpdGUuY3N2KGZpbGU9cGFzdGUoIi4uLy4uL1N1cHBsZW1lbnQvRGF0YXNldCBTMi9XVF8iLG5hbWVzKHd0LmRlcGxldGVkLmdlbmVzKVtpXSwiX2RlcGxldGVkX2dlbmVzLmNzdiIsc2VwPSIiKSx0ZW1wb3JhbC50YWJsZSxxdW90ZSA9IEYscm93Lm5hbWVzID0gRikKfQojd3JpdGUgQ1NWIGZpbGUgd2l0aCBpbmZvcm1hdGlvbiBhYm91dCBvdmVybGFwIGJldHdlZW4gdGltZSBwb2ludHMKd3QuZGVwbGV0ZWQuZ2VuZXMuY29tcGFyaXNvbi50YWJsZTwtbWF0cml4KG5yb3c9NyxuY29sPTcsZGltbmFtZXM9bGlzdChuYW1lcyh3dC5kZXBsZXRlZC5nZW5lcyksbmFtZXMod3QuZGVwbGV0ZWQuZ2VuZXMpKSwwKQpmb3IociBpbiAxOjcpCnsKICBmb3IoYyBpbiAxOjcpCiAgewogICAgd3QuZGVwbGV0ZWQuZ2VuZXMuY29tcGFyaXNvbi50YWJsZVtyLGNdPC1sZW5ndGgoaW50ZXJzZWN0KHd0LmRlcGxldGVkLmdlbmVzW1tyXV0sd3QuZGVwbGV0ZWQuZ2VuZXNbW2NdXSkpCiAgfQp9CiB3cml0ZS5jc3YoZmlsZT0iLi4vLi4vU3VwcGxlbWVudC9EYXRhc2V0IFMyL1dUX2dlbmVfZGVwbGV0aW9uX2NvbXBhcmlzb24uY3N2Iix3dC5kZXBsZXRlZC5nZW5lcy5jb21wYXJpc29uLnRhYmxlKQpgYGAKMy45IENyZWF0ZSBzaW5nbGUgZmlsZXMgZm9yIERhdGEgU2V0IFMxCmBgYHtyfQojd3JpdGUgQ1NWIGZpbGVzIHdpdGggcmF3IHJlYWQgY291bnRzIGZvciBLTyBkZXNpZ25zIGluIFdUIGFuZCBUZXRSIEtPIGxpYnJhcmllcwp0ZW1wb3JhbC50YWJsZTwtY2JpbmQocm93bmFtZXModGV0Ui5rby5yZWFkLmNvdW50cy5udW1lcmljKSx0ZXRSLmtvLmxpYnJhcnkuY291bnQubWF0cml4LndpdGguZ2VuZS5pbmZvW3Jvd25hbWVzKHRldFIua28ucmVhZC5jb3VudHMubnVtZXJpYyksImdlbmUiXSx0ZXRSLmtvLnJlYWQuY291bnRzLm51bWVyaWMpCmNvbG5hbWVzKHRlbXBvcmFsLnRhYmxlKVsxOjZdPC1jKCJEZXNpZ24gSUQiLCJHZW5lIiwiQzAtYSIsIkMwLWIiLCJDMC1jIiwiQzAtZCIpCndyaXRlLmNzdihmaWxlPSIuLi8uLi9TdXBwbGVtZW50L0RhdGFzZXQgUzEvVGV0Ul9yYXdfcmVhZF9jb3VudHMuY3N2Iix0ZW1wb3JhbC50YWJsZSxxdW90ZSA9IEYscm93Lm5hbWVzID0gRikKI3JlcGVhdCBmb3IgV1QKdGVtcG9yYWwudGFibGU8LWNiaW5kKHJvd25hbWVzKHd0LmtvLnJlYWQuY291bnRzLm51bWVyaWMpLHd0LmtvLmxpYnJhcnkuY291bnQubWF0cml4LndpdGguZ2VuZS5pbmZvW3Jvd25hbWVzKHd0LmtvLnJlYWQuY291bnRzLm51bWVyaWMpLCJnZW5lIl0sd3Qua28ucmVhZC5jb3VudHMubnVtZXJpYykKY29sbmFtZXModGVtcG9yYWwudGFibGUpWzE6Nl08LWMoIkRlc2lnbiBJRCIsIkdlbmUiLCJDMC1hIiwiQzAtYiIsIkMwLWMiLCJDMC1kIikKd3JpdGUuY3N2KGZpbGU9Ii4uLy4uL1N1cHBsZW1lbnQvRGF0YXNldCBTMS9XVF9yYXdfcmVhZF9jb3VudHMuY3N2Iix0ZW1wb3JhbC50YWJsZSxxdW90ZSA9IEYscm93Lm5hbWVzID0gRikKI3NhdmUgQ1NWIGZpbGVzIHdpdGggQUxERXgyIG91dHB1dAojdGV0UiBLTyBsaWJyYXJ5CndyaXRlLmNzdihmaWxlPSIuLi8uLi9TdXBwbGVtZW50L0RhdGFzZXQgUzEvVGV0Ul90MSt0ZXRfdnNfdDAuY3N2Iix0ZXRSLmtvLmlxbHIuYzAuYzEucGx1cykKd3JpdGUuY3N2KGZpbGU9Ii4uLy4uL1N1cHBsZW1lbnQvRGF0YXNldCBTMS9UZXRSX3QxLXRldF92c190MC5jc3YiLHRldFIua28uaXFsci5jMC5jMS5taW51cykKd3JpdGUuY3N2KGZpbGU9Ii4uLy4uL1N1cHBsZW1lbnQvRGF0YXNldCBTMS9UZXRSX3QyK3RldF92c190MC5jc3YiLHRldFIua28uaXFsci5jMC5jMi5wbHVzKQp3cml0ZS5jc3YoZmlsZT0iLi4vLi4vU3VwcGxlbWVudC9EYXRhc2V0IFMxL1RldFJfdDItdGV0X3ZzX3QwLmNzdiIsdGV0Ui5rby5pcWxyLmMwLmMyLm1pbnVzKQojd3QgS08gbGlicmFyeQp3cml0ZS5jc3YoZmlsZT0iLi4vLi4vU3VwcGxlbWVudC9EYXRhc2V0IFMxL1dUX3QxK3RldF92c190MC5jc3YiLHd0LmtvLmlxbHIuYzAuYzEucGx1cykKd3JpdGUuY3N2KGZpbGU9Ii4uLy4uL1N1cHBsZW1lbnQvRGF0YXNldCBTMS9XVF90MS10ZXRfdnNfdDAuY3N2Iix3dC5rby5pcWxyLmMwLmMxLm1pbnVzKQp3cml0ZS5jc3YoZmlsZT0iLi4vLi4vU3VwcGxlbWVudC9EYXRhc2V0IFMxL1dUX3QyK3RldF92c190MC5jc3YiLHd0LmtvLmlxbHIuYzAuYzIucGx1cykKd3JpdGUuY3N2KGZpbGU9Ii4uLy4uL1N1cHBsZW1lbnQvRGF0YXNldCBTMS9XVF90Mi10ZXRfdnNfdDAuY3N2Iix3dC5rby5pcWxyLmMwLmMyLm1pbnVzKQojc2F2ZSBDU1YgZmlsZXMgd2l0aCBpbmZvcm1hdGlvbiBvZiBhbGwgZ2VuZXMgYWZmZWN0aW5nIGZpdG5lc3MgaW4gdGhlIFRldFIgS08gbGlicmFyeQojdGhpcyBsZXZlcmFnZXMgcHJldmlvdXNseSBjb25zdHJ1Y3RlZCBtYXRyaXggdGhhdCBjb21waWxlZCBlZmZlY3Qgb2YgZ2VuZSBkZWxldGlvbnMKdGV0Ui5nZW5lLktPLmZpdG5lc3MuZWZmZWN0PC1pbnB1dC5tYXRyaXguZm9yLmhlYXRtYXBbd2hpY2goaW5wdXQubWF0cml4LmZvci5oZWF0bWFwWywiVGV0UiJdIT0wKSwiVGV0UiJdCnRldFIuZ2VuZXMuaW1wYWN0aW5nLmZpdG5lc3M8LW5hbWVzKHRldFIuZ2VuZS5LTy5maXRuZXNzLmVmZmVjdCkKdGV0Ui5kZWxldGlvbi5lZmZlY3Q8LWMoKQp0ZXRSLnNwZWNpZmljaXR5PC1jKCkKZm9yKHIgaW4gMTpsZW5ndGgodGV0Ui5nZW5lLktPLmZpdG5lc3MuZWZmZWN0KSkKewogIGlmKHRldFIuZ2VuZS5LTy5maXRuZXNzLmVmZmVjdFtyXT09MSkKICB7CiAgdGV0Ui5kZWxldGlvbi5lZmZlY3Q8LWModGV0Ui5kZWxldGlvbi5lZmZlY3QsIlBvc2l0aXZlIikKICB9CiAgaWYodGV0Ui5nZW5lLktPLmZpdG5lc3MuZWZmZWN0W3JdPT0tMSkKICB7CiAgdGV0Ui5kZWxldGlvbi5lZmZlY3Q8LWModGV0Ui5kZWxldGlvbi5lZmZlY3QsIk5lZ2F0aXZlIikKICB9CiAgaWYoaW5wdXQubWF0cml4LmZvci5oZWF0bWFwW3RldFIuZ2VuZXMuaW1wYWN0aW5nLmZpdG5lc3Nbcl0sIldUIl09PTApCiAgewogIHRldFIuc3BlY2lmaWNpdHk8LWModGV0Ui5zcGVjaWZpY2l0eSwiWWVzIikKICB9CiAgaWYoaW5wdXQubWF0cml4LmZvci5oZWF0bWFwW3RldFIuZ2VuZXMuaW1wYWN0aW5nLmZpdG5lc3Nbcl0sIldUIl0hPTApCiAgewogIHRldFIuc3BlY2lmaWNpdHk8LWModGV0Ui5zcGVjaWZpY2l0eSwiTm8iKQogIH0KfQp0ZW1wb3JhbC50YWJsZTwtY2JpbmQodGV0Ui5nZW5lcy5pbXBhY3RpbmcuZml0bmVzcyx0ZXRSLmRlbGV0aW9uLmVmZmVjdCx0ZXRSLnNwZWNpZmljaXR5KQpjb2xuYW1lcyh0ZW1wb3JhbC50YWJsZSk8LWMoIkdlbmUiLCJEZWxldGlvbiBlZmZlY3QiLCJUZXRSLXNwZWNpZmljPyIpCnRlbXBvcmFsLnRhYmxlPC10ZW1wb3JhbC50YWJsZVtvcmRlcih0ZW1wb3JhbC50YWJsZVssIkdlbmUiXSksXQp3cml0ZS5jc3YoZmlsZT0iLi4vLi4vU3VwcGxlbWVudC9EYXRhc2V0IFMxL1RldFJfZ2VuZXNfaW1wYWN0aW5nX2ZpdG5lc3MuY3N2Iix0ZW1wb3JhbC50YWJsZSxxdW90ZSA9IEYscm93Lm5hbWVzID0gRikKI2NyZWF0ZSBzaW1pbGFyIHRhYmxlIGZvciBXVCBLTyBsaWJyYXJ5Cnd0LmdlbmUuS08uZml0bmVzcy5lZmZlY3Q8LWlucHV0Lm1hdHJpeC5mb3IuaGVhdG1hcFt3aGljaChpbnB1dC5tYXRyaXguZm9yLmhlYXRtYXBbLCJXVCJdIT0wKSwiV1QiXQp3dC5nZW5lcy5pbXBhY3RpbmcuZml0bmVzczwtbmFtZXMod3QuZ2VuZS5LTy5maXRuZXNzLmVmZmVjdCkKd3QuZGVsZXRpb24uZWZmZWN0PC1jKCkKd3Quc3BlY2lmaWNpdHk8LWMoKQpmb3IociBpbiAxOmxlbmd0aCh3dC5nZW5lLktPLmZpdG5lc3MuZWZmZWN0KSkKewogIGlmKHd0LmdlbmUuS08uZml0bmVzcy5lZmZlY3Rbcl09PTEpCiAgewogIHd0LmRlbGV0aW9uLmVmZmVjdDwtYyh3dC5kZWxldGlvbi5lZmZlY3QsIlBvc2l0aXZlIikKICB9CiAgaWYod3QuZ2VuZS5LTy5maXRuZXNzLmVmZmVjdFtyXT09LTEpCiAgewogIHd0LmRlbGV0aW9uLmVmZmVjdDwtYyh3dC5kZWxldGlvbi5lZmZlY3QsIk5lZ2F0aXZlIikKICB9CiAgaWYoaW5wdXQubWF0cml4LmZvci5oZWF0bWFwW3d0LmdlbmVzLmltcGFjdGluZy5maXRuZXNzW3JdLCJUZXRSIl09PTApCiAgewogIHd0LnNwZWNpZmljaXR5PC1jKHd0LnNwZWNpZmljaXR5LCJZZXMiKQogIH0KICBpZihpbnB1dC5tYXRyaXguZm9yLmhlYXRtYXBbd3QuZ2VuZXMuaW1wYWN0aW5nLmZpdG5lc3Nbcl0sIlRldFIiXSE9MCkKICB7CiAgd3Quc3BlY2lmaWNpdHk8LWMod3Quc3BlY2lmaWNpdHksIk5vIikKICB9Cn0KdGVtcG9yYWwudGFibGU8LWNiaW5kKHd0LmdlbmVzLmltcGFjdGluZy5maXRuZXNzLHd0LmRlbGV0aW9uLmVmZmVjdCx3dC5zcGVjaWZpY2l0eSkKY29sbmFtZXModGVtcG9yYWwudGFibGUpPC1jKCJHZW5lIiwiRGVsZXRpb24gZWZmZWN0IiwiV1Qtc3BlY2lmaWM/IikKdGVtcG9yYWwudGFibGU8LXRlbXBvcmFsLnRhYmxlW29yZGVyKHRlbXBvcmFsLnRhYmxlWywiR2VuZSJdKSxdCndyaXRlLmNzdihmaWxlPSIuLi8uLi9TdXBwbGVtZW50L0RhdGFzZXQgUzEvV1RfZ2VuZXNfaW1wYWN0aW5nX2ZpdG5lc3MuY3N2Iix0ZW1wb3JhbC50YWJsZSxxdW90ZSA9IEYscm93Lm5hbWVzID0gRikKYGBgCjQuMSBGaWcuIDRBCmBgYHtyfQojZnVuY3Rpb24gdG8gY2hhbmdlIGZvcm1hdCBvZiB0aW1lIGRhdGEgc28gaXQgY2FuIGJlIHJlYWQgYnkgR3Jvd3RoY3VydmVyCmNoYW5nZS50aW1lLmZvcm1hdDwtZnVuY3Rpb24odGltZS52ZWN0b3IpCnsKICBvdXRwdXQ8LWMoKQogIGZvcih4IGluIHRpbWUudmVjdG9yKQogIHsKICAgICNyZWFkIHRpbWUgaW4gdGhlIEhIOk1NOlNTIGZvcm1hdCBhbmQgY29udmVydCBpdCB0byBkZWNpbWFsIGZvcm1hdAogICAgY3VycmVudC50aW1lLnBvaW50PC1zdHJzcGxpdCh4LHNwbGl0ID0gIjoiKVtbMV1dCiAgICBvdXRwdXQ8LWMob3V0cHV0LCBhcy5udW1lcmljKGN1cnJlbnQudGltZS5wb2ludFsxXSkgKyAoKGFzLm51bWVyaWMoY3VycmVudC50aW1lLnBvaW50WzNdKSArICg2MCphcy5udW1lcmljKGN1cnJlbnQudGltZS5wb2ludFsyXSkpKS8zNjAwKSkKICB9CiAgb3V0cHV0PC1yb3VuZChvdXRwdXQsZGlnaXRzID0gMykKICBvdXRwdXQKfQojZnVuY3Rpb24gdG8gZXN0aW1hdGUgdGhlIGF2ZXJhZ2UgYW5kIHN0YW5kYXJkIGRldmlhdGlvbiAoc2QpIG9mIGVhY2ggc3RyYWluICh0YWtpbmcgaW50byBhY2NvdW50IGFsbCBvZiBpdHMgcmVwbGljYXRlcykgYXQgZWFjaCB0aW1lIHBvaW50CiN0aGUgaW5wdXQgZGF0YSBmcmFtZSBzaG91bGQgaGF2ZSB0aHJlZSBjb2x1bW5zOiAiVGltZSIsIlN0cmFpbiIgYW5kICJPRCIuIFRoZSBsYXR0ZXIgaXMgdGhlIE9EIHJlYWRpbmdzIGNvbGxlY3RlZCBpbiB0aGUgQmlvc2NyZWVuIGV4cGVyaW1lbnQKY29tcHV0ZS5tZWFuLmFuZC5zZDwtZnVuY3Rpb24oZ3Jvd3RoLmRmKQp7CiAgb3V0cHV0PC1jKCkKICBtZWFzdXJlZC50aW1lLnBvaW50czwtdW5pcXVlKGdyb3d0aC5kZiRUaW1lKQogICNmb3IgZWFjaCB0aW1lIHBvaW50CiAgZm9yKHQgaW4gbWVhc3VyZWQudGltZS5wb2ludHMpCiAgewogICAgI2ZvciBlYWNoIHN0cmFpbgogICAgZm9yKHMgaW4gdW5pcXVlKGdyb3d0aC5kZiRTdHJhaW4pKQogICAgewogICAgICNjb21wdXRlIG1lYW4gT0QgcmVhZGluZyB2YWx1ZSAgICAKICAgICBhdmVyYWdlLmN1cnJlbnQuc3RyYWluLmFuZC50aW1lLnBvaW50PC1tZWFuKGdyb3d0aC5kZiRPRFt3aGljaChncm93dGguZGYkU3RyYWluPT1zICYgZ3Jvd3RoLmRmJFRpbWU9PXQpXSkKICAgICAjY29tcHV0ZSBjb3JyZXNwb25kaW5nIFNECiAgICAgc2QuY3VycmVudC5zdHJhaW4uYW5kLnRpbWUucG9pbnQ8LXNkKGdyb3d0aC5kZiRPRFt3aGljaChncm93dGguZGYkU3RyYWluPT1zICYgZ3Jvd3RoLmRmJFRpbWU9PXQpXSkKICAgICBvdXRwdXQ8LXJiaW5kKG91dHB1dCxjYmluZCh0LHMsYXZlcmFnZS5jdXJyZW50LnN0cmFpbi5hbmQudGltZS5wb2ludCxzZC5jdXJyZW50LnN0cmFpbi5hbmQudGltZS5wb2ludCkpCiAgICB9CiAgfQogICNhZGQgY29sdW1uIG5hbWVzCiAgY29sbmFtZXMob3V0cHV0KTwtYygiVGltZSIsIlN0cmFpbiIsIk9EIiwic2QiKQogICNtYWtlIHN1cmUgZGF0YSBmcmFtZSBmb3JtYXQgaXMgZ29vZCBmb3IgZG93bnN0cmVhbSBhbmFseXNlcwogIG91dHB1dDwtYXMuZGF0YS5mcmFtZShvdXRwdXQpCiAgb3V0cHV0JFRpbWU8LWFzLm51bWVyaWMoYXMudmVjdG9yKG91dHB1dCRUaW1lKSkKICBvdXRwdXQkT0Q8LWFzLm51bWVyaWMoYXMudmVjdG9yKG91dHB1dCRPRCkpCiAgb3V0cHV0JHNkPC1hcy5udW1lcmljKGFzLnZlY3RvcihvdXRwdXQkc2QpKQogIG91dHB1dAp9CiNyZWFkIE9EIHJlYWRpbmdzIGZyb20gQmlvc2NyZWVuIGV4cGVyaW1lbnQgdG8gZ2VuZXJhdGUgY29ycmVzcG9uZGluZyBncm93dGggY3VydmVzCiN0aGVyZSB3ZXJlIGZpdmUgc3RyYWlucyBpbiB0aGUgZXhwZXJpbWVudAojZm9yIGVhY2ggc3RyYWluL3RldHJhY3ljbGluZSBjb25jZW50cmF0aW9uLCB0aGVyZSBhcmUgdGhyZWUgYmlvbG9naWNhbCByZXBsaWNhdGVzIChlYWNoIG9uZSB3aXRoIHR3byByZXBsaWNhdGVzKQojYmlvc2NyZWVuIGV4cGVyaW1lbnQgd2FzIHBlcmZvcm1lZCBmb3IgYSB0b3RhbCBvZiA0OGgKZ3Jvd3RoLmRhdGE8LXJlYWQuY3N2KCIuLi9EYXRhL0ZpdG5lc3NfQmlvc2NyZWVuQy8yMDIyMDUwNF9mb3JtYXR0ZWRfZGF0YS5jc3YiLHJvdy5uYW1lcz0xKQojY2hhbmdlIHRpbWUgZm9ybWF0CnRpbWUuZGF0YTwtY2hhbmdlLnRpbWUuZm9ybWF0KHJvd25hbWVzKGdyb3d0aC5kYXRhKSkKI3VwZGF0ZSByb3cgbmFtZXMgd2l0aCB0aW1lIGluIG5ldyBmb3JtYXQKcm93bmFtZXMoZ3Jvd3RoLmRhdGEpPC1yb3VuZCh0aW1lLmRhdGEsZGlnaXRzID0gMikKI25vcm1hbGl6ZSBkYXRhIGJ5IHN1YnRyYWN0aW5nIG1pbmltdW0gT0QgcmVhZGluZyBwZXIgd2VsbApncm93dGguZGF0YS5ub3JtYWxpemVkPC1jKCkKZm9yKGkgaW4gMTpuY29sKGdyb3d0aC5kYXRhKSkKewogIG1pbmltdW0ucmVhZGluZy5jdXJyZW50LndlbGw8LW1pbihncm93dGguZGF0YVssaV0pCiAgZ3Jvd3RoLmRhdGEubm9ybWFsaXplZDwtY2JpbmQoZ3Jvd3RoLmRhdGEubm9ybWFsaXplZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm93dGguZGF0YVssaV0tbWluaW11bS5yZWFkaW5nLmN1cnJlbnQud2VsbCkKfQojYWRkIGNvbHVtbiBuYW1lcwpjb2xuYW1lcyhncm93dGguZGF0YS5ub3JtYWxpemVkKTwtY29sbmFtZXMoZ3Jvd3RoLmRhdGEpCiNhZGQgcm93IG5hbWVzCnJvd25hbWVzKGdyb3d0aC5kYXRhLm5vcm1hbGl6ZWQpPC1yb3duYW1lcyhncm93dGguZGF0YSkKI3RoZXNlIGFyZSB0aGUgdGV0cmFjeWNsaW5lIGNvbmNlbnRyYXRpb25zIGluY2x1ZGVkIGluIHRoZSBleHBlcmltZW50CnRldHJhY3ljbGluZS5jb25jZW50cmF0aW9uczwtc2VxKDAsMjQsYnk9NCkgIyB1Zy9tbAojbGFiZWxzIGZvciB0aGUgZml2ZSBzdHJhaW5zIGluIHRoZSBkYXRhc2V0CnN0cmFpbnM8LWMoIldUIiwiV1RhcmNBIiwiVGV0UiIsIlRldFJhcmNBIiwicFJCM2FyY0EiKQojY29sb3IgdG8gYmUgdXNlZCBmb3IgZWFjaCBzdHJhaW4Kc3RyYWluLmNvbG9yczwtYyhXVD0iIzY2QzJBNSIsV1RhcmNBPSIjRkM4RDYyIixUZXRSPSIjOERBMENCIixUZXRSYXJjQT0iI0U3OEFDMyIscFJCM2FyY0E9IiNBNkQ4NTQiKQojdGhlIE9EIGRhdGEgaGFzIGJlZW4gZm9ybWF0dGVkIHN1Y2ggYXMgdGhlIG5hbWUgb2YgZWFjaCB3ZWxsIGNvbnRhaW5zIHRoZSBpbmZvcm1hdGlvbiBhYm91dCB0aGUgc3RyYWluIGFuZCB0aGUgdGV0cmFjeWNsaW5lIGNvbmNlbnRyYXRpb24KI2ZvciBleGFtcGxlOiBUZXRSXzIwIG1lYW5zIHRoYXQgdGhlIHdlbGwgd2FzIGlub2N1bGF0ZWQgd2l0aCB0aGUgVGV0UiBzdHJhaW4gYW5kIDIwIHVnL21sIG9mIHRldHJhY3ljbGluZQojY3JlYXRlIEZpZy4gM0EgbGVmdCBwYW5lbCAoaWUsIGFudGliaW90aWMtZnJlZSkKI2NyZWF0ZSBkYXRhIGZyYW1lCmFudGliaW90aWMuZnJlZS5jdWx0dXJlcy5kZjwtYygpCiNsb29wIHRvIGNvbXBpbGUgT0QgZGF0YSBmb3IgYWxsIGZpdmUgc3RyYWlucwpmb3IocyBpbiBzdHJhaW5zKQp7CiAgY3VycmVudC5zdHJhaW4uY29uY2VudHJhdGlvbjwtcGFzdGUocywwLHNlcD0iXyIpCiAgI2lkZW50aWZ5IHRoZSBwb3NpdGlvbiBvZiBhbGwgcmVwbGljYXRlcyBmb3IgdGhlIGN1cnJlbnQgc3RyYWluL2NvbmNlbnRyYXRpb24gY29tYmluYXRpb24KICByZXBsaWNhdGVzLnBvc2l0aW9uczwtZ3JlcChjdXJyZW50LnN0cmFpbi5jb25jZW50cmF0aW9uLGNvbG5hbWVzKGdyb3d0aC5kYXRhLm5vcm1hbGl6ZWQpKQogICNhZGQgT0QgcmVhZGluZ3MgKGZpcnN0IDI0aCkgb2YgdGhlIHJlbGV2YW50IHJlcGxpY2F0ZXMgdG8gdGhlIGRhdGEgZnJhbWUKICBmb3IociBpbiByZXBsaWNhdGVzLnBvc2l0aW9ucykKICB7CiAgICBhbnRpYmlvdGljLmZyZWUuY3VsdHVyZXMuZGY8LXJiaW5kKGFudGliaW90aWMuZnJlZS5jdWx0dXJlcy5kZixjYmluZChyb3duYW1lcyhncm93dGguZGF0YS5ub3JtYWxpemVkKVsxOjUwXSxncm93dGguZGF0YS5ub3JtYWxpemVkWzE6NTAscl0scmVwKHMsNTApKSkKICB9Cn0KI2FkZCBjb2x1bW4gbmFtZXMKY29sbmFtZXMoYW50aWJpb3RpYy5mcmVlLmN1bHR1cmVzLmRmKTwtYygiVGltZSIsIk9EIiwiU3RyYWluIikKI21ha2Ugc3VyZSBkYXRhIGZyYW1lIGZvcm1hdCBpcyBjb3JyZWN0CmFudGliaW90aWMuZnJlZS5jdWx0dXJlcy5kZjwtYXMuZGF0YS5mcmFtZShhbnRpYmlvdGljLmZyZWUuY3VsdHVyZXMuZGYpCmFudGliaW90aWMuZnJlZS5jdWx0dXJlcy5kZiRTdHJhaW4gPC0gYXMuZmFjdG9yKGFudGliaW90aWMuZnJlZS5jdWx0dXJlcy5kZiRTdHJhaW4pCmFudGliaW90aWMuZnJlZS5jdWx0dXJlcy5kZiRUaW1lPC0gYXMubnVtZXJpYyhhcy52ZWN0b3IoYW50aWJpb3RpYy5mcmVlLmN1bHR1cmVzLmRmJFRpbWUpKQphbnRpYmlvdGljLmZyZWUuY3VsdHVyZXMuZGYkT0Q8LSBhcy5udW1lcmljKGFzLnZlY3RvcihhbnRpYmlvdGljLmZyZWUuY3VsdHVyZXMuZGYkT0QpKQojY29tcHV0ZSBtZWFuIGFuZCBzZCBwZXIgc3RyYWluL2NvbmNlbnRyYXRpb24vdGltZSBwb2ludCBjb21iaW5hdGlvbgphbnRpYmlvdGljLmZyZWUuY3VsdHVyZXMuZGYudjIgPC0gY29tcHV0ZS5tZWFuLmFuZC5zZChhbnRpYmlvdGljLmZyZWUuY3VsdHVyZXMuZGYpCiNjcmVhdGUgZ2dwbG90IG9iamVjdCB0byBnZW5lcmF0ZSBmaW5hbCBmaWd1cmUKYW50aWJpb3RpYy5mcmVlLnN1YnBhbmVsPC0gZ2dwbG90KGFudGliaW90aWMuZnJlZS5jdWx0dXJlcy5kZi52MiwgYWVzKHg9VGltZSx5PU9ELCBncm91cD1TdHJhaW4sY29sb3VyPVN0cmFpbikpICsgCiAgZ2VvbV9saW5lKCkgKwogIGdlb21fcG9pbnQoKSsKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluPU9ELXNkLCB5bWF4PU9EK3NkKSwgd2lkdGg9MC43NSxhbHBoYT0wLjc1KSsKICB0aGVtZV9jbGFzc2ljKCkKI2NyZWF0ZSBGaWcuIDRBIHJpZ2h0IHBhbmVsCiN0cmVhdG1lbnQgd2l0aCAyMCB1Zy9tbCBvZiB0ZXRyYWN5Y2xpbmUKdGV0LmNvbmNlbnRyYXRpb248LSAyMAojY3JlYXRlIGRhdGEgZnJhbWUgdG8gc3RvcmUgT0QgcmVhZGluZ3MgCiNvbmx5IFRldFIsIFRldFIgRGFyY0EgYW5kIFRldFIgRGFyY0EgKyBwUkIzLWFyY0EgKGVwaXNvbWFsIGNvbXBsZW1lbnRlZCBzdHJhaW4pIHdlcmUgdHJlYXRlZCB3aXRoIHRldHJhY3ljbGluZQp0ZXRyYWN5Y2xpbmUudHJlYXRlZC5jdWx0dXJlcy5kZjwtYygpCiAgZm9yKHMgaW4gc3RyYWluc1szOjVdKQogIHsKICAgIGN1cnJlbnQuc3RyYWluLmNvbmNlbnRyYXRpb248LXBhc3RlKHMsdGV0LmNvbmNlbnRyYXRpb24sc2VwPSJfIikKICAgICNpZGVudGlmeSB0aGUgcG9zaXRpb24gb2YgYWxsIHJlcGxpY2F0ZXMgZm9yIHRoZSBjdXJyZW50IHN0cmFpbi9jb25jZW50cmF0aW9uIGNvbWJpbmF0aW9uCiAgICByZXBsaWNhdGVzLnBvc2l0aW9uczwtZ3JlcChjdXJyZW50LnN0cmFpbi5jb25jZW50cmF0aW9uLGNvbG5hbWVzKGdyb3d0aC5kYXRhKSkKICAgICNhZGQgT0QgcmVhZGluZ3MgKGZ1bGwgNDhoKSBmb3IgdGhlIHJlbGV2YW50IHJlcGxpY2F0ZXMgdG8gdGhlIGRhdGEgZnJhbWUKICAgIGZvcihyIGluIHJlcGxpY2F0ZXMucG9zaXRpb25zKQogICAgewogICAgICB0ZXRyYWN5Y2xpbmUudHJlYXRlZC5jdWx0dXJlcy5kZjwtcmJpbmQodGV0cmFjeWNsaW5lLnRyZWF0ZWQuY3VsdHVyZXMuZGYsY2JpbmQocm93bmFtZXMoZ3Jvd3RoLmRhdGEubm9ybWFsaXplZCksZ3Jvd3RoLmRhdGEubm9ybWFsaXplZFsscl0scmVwKHMsbnJvdyhncm93dGguZGF0YS5ub3JtYWxpemVkKSkpKQogICAgfQogIH0KICAjYWRkIGNvbHVtbiBuYW1lcyAgCiAgY29sbmFtZXModGV0cmFjeWNsaW5lLnRyZWF0ZWQuY3VsdHVyZXMuZGYpPC1jKCJUaW1lIiwiT0QiLCJTdHJhaW4iKQogICNtYWtlIHN1cmUgZGF0YSBmcmFtZSBmb3JtYXQgaXMgY29ycmVjdAogIHRldHJhY3ljbGluZS50cmVhdGVkLmN1bHR1cmVzLmRmPC1hcy5kYXRhLmZyYW1lKHRldHJhY3ljbGluZS50cmVhdGVkLmN1bHR1cmVzLmRmKQogIHRldHJhY3ljbGluZS50cmVhdGVkLmN1bHR1cmVzLmRmJFN0cmFpbiA8LSBhcy5mYWN0b3IodGV0cmFjeWNsaW5lLnRyZWF0ZWQuY3VsdHVyZXMuZGYkU3RyYWluKQogIHRldHJhY3ljbGluZS50cmVhdGVkLmN1bHR1cmVzLmRmJFRpbWU8LSBhcy5udW1lcmljKGFzLnZlY3Rvcih0ZXRyYWN5Y2xpbmUudHJlYXRlZC5jdWx0dXJlcy5kZiRUaW1lKSkKICB0ZXRyYWN5Y2xpbmUudHJlYXRlZC5jdWx0dXJlcy5kZiRPRDwtIGFzLm51bWVyaWMoYXMudmVjdG9yKHRldHJhY3ljbGluZS50cmVhdGVkLmN1bHR1cmVzLmRmJE9EKSkKICAjY29tcHV0ZSBtZWFuIGFuZCBzZCBwZXIgc3RyYWluL2NvbmNlbnRyYXRpb24vdGltZSBwb2ludCBjb21iaW5hdGlvbgogIHRldHJhY3ljbGluZS50cmVhdGVkLmN1bHR1cmVzLmRmLnYyIDwtIGNvbXB1dGUubWVhbi5hbmQuc2QodGV0cmFjeWNsaW5lLnRyZWF0ZWQuY3VsdHVyZXMuZGYpCiAgI2NyZWF0ZSBnZ3Bsb3Qgb2JqZWN0IHRvIGdlbmVyYXRlIGZpbmFsIGZpZ3VyZQogIHRldHJhY3ljbGluZS50cmVhdGVkLnN1YnBhbmVsPC0gZ2dwbG90KHRldHJhY3ljbGluZS50cmVhdGVkLmN1bHR1cmVzLmRmLnYyLCBhZXMoeD1UaW1lLHk9T0QsIGdyb3VwPVN0cmFpbixjb2xvdXI9U3RyYWluKSkgKyAKICAgIGdlb21fbGluZSgpICsKICAgIGdlb21fcG9pbnQoKSsKICAgIGdlb21fZXJyb3JiYXIoYWVzKHltaW49T0Qtc2QsIHltYXg9T0Qrc2QpLCB3aWR0aD0wLjc1LGFscGhhPTAuMTUpKwogICAgdGhlbWVfY2xhc3NpYygpCiAgI2dlbmVyYXRlIEZpZy4gNEEKZ3JpZC5hcnJhbmdlKGFudGliaW90aWMuZnJlZS5zdWJwYW5lbCArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9c3RyYWluLmNvbG9ycykrIAp0aGVtZShheGlzLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTApLGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xMCxmYWNlPSJib2xkIikpICsgeGxhYigiVGltZSAoaCkiKSArIHlsYWIoIk9ENjAwIikrZ2d0aXRsZSgiW1RFVF09MCIpLHRldHJhY3ljbGluZS50cmVhdGVkLnN1YnBhbmVsKyBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPXN0cmFpbi5jb2xvcnNbMzo1XSkrIAp0aGVtZShheGlzLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTApLGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xMCxmYWNlPSJib2xkIikpICsgeGxhYigiVGltZSAoaCkiKSArIHlsYWIoIk9ENjAwIikrZ2d0aXRsZSgiW1RFVF09MjB1Zy9tbCIpLG5yb3c9MSkKYGBgCjQuMiBGaWcuIFMzCmBgYHtyfQojcGxvdCBncm93dGggY3VydmVzIG9mIFdUIGFuZCBUZXRSIGluIGFudGliaW90aWMtZnJlZSBjdWx0dXJlcyAKI2NyZWF0ZSBnZ3Bsb3Qgb2JqZWN0CnRlbXBvcmFsLnBsb3Q8LSBnZ3Bsb3QoYW50aWJpb3RpYy5mcmVlLmN1bHR1cmVzLmRmLnYyW3doaWNoKGFudGliaW90aWMuZnJlZS5jdWx0dXJlcy5kZi52MiRTdHJhaW4gPT0iV1QiIHwgYW50aWJpb3RpYy5mcmVlLmN1bHR1cmVzLmRmLnYyJFN0cmFpbiA9PSAiVGV0UiIpLF0KICAgICAgICAgICAgICAgICAgICAgICAsIGFlcyh4PVRpbWUseT1PRCwgZ3JvdXA9U3RyYWluLGNvbG91cj1TdHJhaW4pKSArIAogIGdlb21fbGluZSgpICsKICBnZW9tX3BvaW50KCkrCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbj1PRC1zZCwgeW1heD1PRCtzZCksIHdpZHRoPTAuNzUsYWxwaGE9MC41KSsKICB0aGVtZV9jbGFzc2ljKCkKcHJpbnQodGVtcG9yYWwucGxvdCArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9c3RyYWluLmNvbG9yc1tjKDEsMyldKSsgCiAgICAgICAgdGhlbWUoYXhpcy50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEwKSxheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTAsZmFjZT0iYm9sZCIpKSArIHhsYWIoIlRpbWUgKGgpIikreWxhYigiT0Q2MDAiKStnZ3RpdGxlKCJGaWcuIFMzIikpCiNlc3RpbWF0ZSBmaXRuZXNzIHBhcmFtZXRlcnMgc2hvd24gaW4gRmlnLiBTMyB3aXRoIEdyb3d0aGN1cnZlciAoZm9yIHRoZSBmaXJzdCAyNGggb2YgZ3Jvd3RoKQp0aW1lLnZlY3RvcjwtYXMudmVjdG9yKHRpbWUuZGF0YSkKaW5wdXQubWF0cml4Lmdyb3d0aGN1cnZlcjwtYXMuZGF0YS5mcmFtZShjYmluZCh0aW1lLmRhdGFbMTo1MF0sZ3Jvd3RoLmRhdGEubm9ybWFsaXplZFsxOjUwLF0pKQojcmVuYW1lIGNvbHVtbiB3aXRoIHRpbWUgdmFsdWVzCmNvbG5hbWVzKGlucHV0Lm1hdHJpeC5ncm93dGhjdXJ2ZXIpWzFdPC0idGltZSIKI3J1biBHcm93dGhjdXJ2ZXIKZ3Jvd3RoY3VydmVyLm91dHB1dCA8LSBTdW1tYXJpemVHcm93dGhCeVBsYXRlKGlucHV0Lm1hdHJpeC5ncm93dGhjdXJ2ZXIpCiNwcmludCBlc3RpbWF0ZWQgbWF4IGdyb3d0aCByYXRlIChtdSkgZm9yIFdUIGFuZCBUZXRSIGluIGFudGliaW90aWMtZnJlZSBtZWRpdW0KcHJpbnQocGFzdGUoIm11IChXVCBpbiBMQiB3aXRob3V0IHRldHJhY3ljbGluZSkgd2FzOiIscm91bmQobWVhbihncm93dGhjdXJ2ZXIub3V0cHV0W2dyZXAoIldUXzAiLGdyb3d0aGN1cnZlci5vdXRwdXQkc2FtcGxlKSwiciJdKSxkaWdpdHM9Miksc2VwPSIiKSkKcHJpbnQocGFzdGUoIm11IChUZXRSIGluIExCIHdpdGhvdXQgdGV0cmFjeWNsaW5lKSB3YXM6Iixyb3VuZChtZWFuKGdyb3d0aGN1cnZlci5vdXRwdXRbZ3JlcCgiVGV0Ul8wIixncm93dGhjdXJ2ZXIub3V0cHV0JHNhbXBsZSksInIiXSksZGlnaXRzPTIpLHNlcD0iIikpCiNwcmludCBlc3RpbWF0ZWQgYXJlYSB1bmRlciB0aGUgZ3Jvd3RoIGN1cnZlIChBVUMpIHZhbHVlcyBmb3IgV1QgYW5kIFRldFIgaW4gYW50aWJpb3RpYy1mcmVlIG1lZGl1bQpwcmludChwYXN0ZSgiQVVDIChXVCBpbiBMQiB3aXRob3V0IHRldHJhY3ljbGluZSkgd2FzOiIscm91bmQobWVhbihncm93dGhjdXJ2ZXIub3V0cHV0W2dyZXAoIldUXzAiLGdyb3d0aGN1cnZlci5vdXRwdXQkc2FtcGxlKSwiYXVjX2UiXSksZGlnaXRzPTIpLHNlcD0iIikpCnByaW50KHBhc3RlKCJBVUMgKFRldFIgaW4gTEIgd2l0aG91dCB0ZXRyYWN5Y2xpbmUpIHdhczoiLHJvdW5kKG1lYW4oZ3Jvd3RoY3VydmVyLm91dHB1dFtncmVwKCJUZXRSXzAiLGdyb3d0aGN1cnZlci5vdXRwdXQkc2FtcGxlKSwiYXVjX2UiXSksZGlnaXRzPTIpLHNlcD0iIikpCmBgYAo0LjMgRmlnLiA0Qi1DCmBgYHtyfQojcmVhZCBPRCBkYXRhIGNvbGxlY3RlZCBpbiBleHBlcmltZW50IHRvIGV2YWx1YXRlIHRoZSBlZmZlY3Qgb2YgYXJjQSBkZWxldGlvbiBpbiBXVCBhbmQgVGV0UiBvdmVyIHRocmVlIGdyb3d0aCBjeWNsZXMKI2luIGVhY2ggY3ljbGUsIGN1bHR1cmVzIHdlcmUgc3RhcnRlZCBhdCBhbiBPRDYwMCBvZiAwLjEgYW5kIGdyb3duIHRvIGFuIE9ENjAwIG9mIDEuMAojYW5kIHRoZXJlYWZ0ZXIgZGlsdXRlZCBpbiBmcmVzaCBtZWRpdW0gdG8gT0Q2MDAgb2YgMC4xIHRvIHN0YXJ0IGEgbmV3IGN5Y2xlIG9mIGdyb3d0aAojdGhyZWUgcmVwbGljYXRlcyBwZXIgc3RyYWluL2FudGliaW90aWMgY29uY2VudHJhdGlvbiB3ZXJlIGluY2x1ZGVkCiNsYXN0IHR3byBjb2x1bW5zIGFyZSBMQiBjb250cm9scyAKY3ljbGljLmdyb3d0aC5vZDwtcmVhZC5jc3YoIi4uL0RhdGEvY3ljbGljX2dyb3d0aC9tYWNyb2RpbHV0aW9uX2N5Y2xpY19ncm93dGhfZXhwZXJpbWVudF9PRF9kYXRhLmNzdiIsaGVhZGVyPVQpCiNjaGFuZ2UgZm9ybWF0IG9mIHRpbWUgYXMgYmVmb3JlCmN5Y2xpYy5ncm93dGgub2QkVGltZTwtY2hhbmdlLnRpbWUuZm9ybWF0KGN5Y2xpYy5ncm93dGgub2QkVGltZSkKcGFyKG1mcm93PWMoMSwzKSkKI3Bsb3QgaW5kaXZpZHVhbCBncm93dGggY3VydmVzIG9mIFRldFIgcmVwbGljYXRlcyBpbiB0ZXRyYWN5Y2xpbmUtZnJlZSBMQgojcmVwbGljYXRlIEEKcGxvdCh4PWN5Y2xpYy5ncm93dGgub2QkVGltZVt3aGljaChjeWNsaWMuZ3Jvd3RoLm9kJFRldFJfMF9BIT0iIildLHk9Y3ljbGljLmdyb3d0aC5vZCRUZXRSXzBfQVt3aGljaChjeWNsaWMuZ3Jvd3RoLm9kJFRldFJfMF9BIT0iIildLGNvbD1zdHJhaW4uY29sb3JzWyJUZXRSIl0scGNoPTAsdHlwZT0ibyIseGxhYj0iVGltZSAoaCkiLHlsYWI9Ik9ENjAwIix4bGltPWMoMCwxMCkseWxpbT1jKDAsMS4xKSxjZXguYXhpcz0xLjUsY2V4LmxhYj0xLjUsbWFpbj0iW1RFVF09MCIpICAKI3JlcGxpY2F0ZSBCCnBvaW50cyh4PWN5Y2xpYy5ncm93dGgub2QkVGltZVt3aGljaChjeWNsaWMuZ3Jvd3RoLm9kJFRldFJfMF9CIT0iIildLHk9Y3ljbGljLmdyb3d0aC5vZCRUZXRSXzBfQlt3aGljaChjeWNsaWMuZ3Jvd3RoLm9kJFRldFJfMF9CIT0iIildLGNvbD1zdHJhaW4uY29sb3JzWyJUZXRSIl0scGNoPTEsdHlwZT0ibyIpICAKI3JlcGxpY2F0ZSBDCnBvaW50cyh4PWN5Y2xpYy5ncm93dGgub2QkVGltZVt3aGljaChjeWNsaWMuZ3Jvd3RoLm9kJFRldFJfMF9DIT0iIildLHk9Y3ljbGljLmdyb3d0aC5vZCRUZXRSXzBfQ1t3aGljaChjeWNsaWMuZ3Jvd3RoLm9kJFRldFJfMF9DIT0iIildLGNvbD1zdHJhaW4uY29sb3JzWyJUZXRSIl0scGNoPTIsdHlwZT0ibyIpICAKI3Bsb3QgaW5kaXZpZHVhbCBncm93dGggY3VydmVzIG9mIFRldFIgRGFyY0EgcmVwbGljYXRlcyBpbiB0ZXRyYWN5Y2xpbmUtZnJlZSBMQgojcmVwbGljYXRlIEEKcG9pbnRzKHg9Y3ljbGljLmdyb3d0aC5vZCRUaW1lW3doaWNoKGN5Y2xpYy5ncm93dGgub2QkVGV0UmFyY0FfMF9BIT0iIildLHk9Y3ljbGljLmdyb3d0aC5vZCRUZXRSYXJjQV8wX0Fbd2hpY2goY3ljbGljLmdyb3d0aC5vZCRUZXRSYXJjQV8wX0EhPSIiKV0sY29sPXN0cmFpbi5jb2xvcnNbIlRldFJhcmNBIl0scGNoPTAsdHlwZT0ibyIpICAKI3JlcGxpY2F0ZSBCCnBvaW50cyh4PWN5Y2xpYy5ncm93dGgub2QkVGltZVt3aGljaChjeWNsaWMuZ3Jvd3RoLm9kJFRldFJhcmNBXzBfQiE9IiIpXSx5PWN5Y2xpYy5ncm93dGgub2QkVGV0UmFyY0FfMF9CW3doaWNoKGN5Y2xpYy5ncm93dGgub2QkVGV0UmFyY0FfMF9CIT0iIildLGNvbD1zdHJhaW4uY29sb3JzWyJUZXRSYXJjQSJdLHBjaD0xLHR5cGU9Im8iKSAgCiNyZXBsaWNhdGUgQwpwb2ludHMoeD1jeWNsaWMuZ3Jvd3RoLm9kJFRpbWVbd2hpY2goY3ljbGljLmdyb3d0aC5vZCRUZXRSYXJjQV8wX0MhPSIiKV0seT1jeWNsaWMuZ3Jvd3RoLm9kJFRldFJhcmNBXzBfQ1t3aGljaChjeWNsaWMuZ3Jvd3RoLm9kJFRldFJhcmNBXzBfQyE9IiIpXSxjb2w9c3RyYWluLmNvbG9yc1siVGV0UmFyY0EiXSxwY2g9Mix0eXBlPSJvIikgIAphYmxpbmUoaD0xLGNvbD0iZGFya2dyZXkiLGx0eT0yKQojcGxvdCBpbmRpdmlkdWFsIGdyb3d0aCBjdXJ2ZXMgb2YgVGV0UiByZXBsaWNhdGVzIGluIExCIHdpdGggMjAgdWcvbWwgb2YgdGV0cmFjeWNsaW5lCiNyZXBsaWNhdGUgQQpwbG90KHg9Y3ljbGljLmdyb3d0aC5vZCRUaW1lW3doaWNoKGN5Y2xpYy5ncm93dGgub2QkVGV0Ul8yMF9BIT0iIildLHk9Y3ljbGljLmdyb3d0aC5vZCRUZXRSXzIwX0Fbd2hpY2goY3ljbGljLmdyb3d0aC5vZCRUZXRSXzIwX0EhPSIiKV0sY29sPXN0cmFpbi5jb2xvcnNbIlRldFIiXSxwY2g9MCx0eXBlPSJvIix4bGFiPSJUaW1lIChoKSIseWxhYj0iT0Q2MDAiLHhsaW09YygwLDQwKSx5bGltPWMoMCwxLjEpLGNleC5heGlzPTEuNSxjZXgubGFiPTEuNSxtYWluPSJbVEVUXT0yMCB1Zy9tbCIpICAKI3JlcGxpY2F0ZSBCCnBvaW50cyh4PWN5Y2xpYy5ncm93dGgub2QkVGltZVt3aGljaChjeWNsaWMuZ3Jvd3RoLm9kJFRldFJfMjBfQiE9IiIpXSx5PWN5Y2xpYy5ncm93dGgub2QkVGV0Ul8yMF9CW3doaWNoKGN5Y2xpYy5ncm93dGgub2QkVGV0Ul8yMF9CIT0iIildLGNvbD1zdHJhaW4uY29sb3JzWyJUZXRSIl0scGNoPTEsdHlwZT0ibyIpICAKI3JlcGxpY2F0ZSBDCnBvaW50cyh4PWN5Y2xpYy5ncm93dGgub2QkVGltZVt3aGljaChjeWNsaWMuZ3Jvd3RoLm9kJFRldFJfMjBfQyE9IiIpXSx5PWN5Y2xpYy5ncm93dGgub2QkVGV0Ul8yMF9DW3doaWNoKGN5Y2xpYy5ncm93dGgub2QkVGV0Ul8yMF9DIT0iIildLGNvbD1zdHJhaW4uY29sb3JzWyJUZXRSIl0scGNoPTIsdHlwZT0ibyIpICAKI3Bsb3QgaW5kaXZpZHVhbCBncm93dGggY3VydmVzIG9mIFRldFIgRGFyY0EgcmVwbGljYXRlcyBpbiBMQiB3aXRoIDIwIHVnL21sCiNyZXBsaWNhdGUgQQpwb2ludHMoeD1jeWNsaWMuZ3Jvd3RoLm9kJFRpbWVbd2hpY2goY3ljbGljLmdyb3d0aC5vZCRUZXRSYXJjQV8yMF9BIT0iIildLHk9Y3ljbGljLmdyb3d0aC5vZCRUZXRSYXJjQV8yMF9BW3doaWNoKGN5Y2xpYy5ncm93dGgub2QkVGV0UmFyY0FfMjBfQSE9IiIpXSxjb2w9c3RyYWluLmNvbG9yc1siVGV0UmFyY0EiXSxwY2g9MCx0eXBlPSJvIikgIAojcmVwbGljYXRlIEIKcG9pbnRzKHg9Y3ljbGljLmdyb3d0aC5vZCRUaW1lW3doaWNoKGN5Y2xpYy5ncm93dGgub2QkVGV0UmFyY0FfMjBfQiE9IiIpXSx5PWN5Y2xpYy5ncm93dGgub2QkVGV0UmFyY0FfMjBfQlt3aGljaChjeWNsaWMuZ3Jvd3RoLm9kJFRldFJhcmNBXzIwX0IhPSIiKV0sY29sPXN0cmFpbi5jb2xvcnNbIlRldFJhcmNBIl0scGNoPTEsdHlwZT0ibyIpICAKI3JlcGxpY2F0ZSBDCnBvaW50cyh4PWN5Y2xpYy5ncm93dGgub2QkVGltZVt3aGljaChjeWNsaWMuZ3Jvd3RoLm9kJFRldFJhcmNBXzIwX0MhPSIiKV0seT1jeWNsaWMuZ3Jvd3RoLm9kJFRldFJhcmNBXzIwX0Nbd2hpY2goY3ljbGljLmdyb3d0aC5vZCRUZXRSYXJjQV8yMF9DIT0iIildLGNvbD1zdHJhaW4uY29sb3JzWyJUZXRSYXJjQSJdLHBjaD0yLHR5cGU9Im8iKSAgCmFibGluZShoPTEsY29sPSJkYXJrZ3JleSIsbHR5PTIpCiNhZGQgbGVnZW5kCnBsb3QubmV3KCkKbGVnZW5kKCJjZW50ZXIiLGNvbD1zdHJhaW4uY29sb3JzW2MoIlRldFIiLCJUZXRSYXJjQSIpXSxsZWdlbmQgPSBjKCJUZXRSIixleHByZXNzaW9uKHBhc3RlKCJUZXRSICIsRGVsdGEsICJhcmNBIikpKSxsdHk9MSkKYGBgCjQuNCBGaWcuIFM2CmBgYHtyfQojY3JlYXRlIHNhbWUgcGxvdCBmb3IgV1QgYW5kIFdUIERhcmNBCnBhcihtZnJvdz1jKDEsMykpCiNwbG90IGluZGl2aWR1YWwgZ3Jvd3RoIGN1cnZlcyBvZiBXVCByZXBsaWNhdGVzIGluIHRldHJhY3ljbGluZS1mcmVlIExCCiNyZXBsaWNhdGUgQQpwbG90KHg9Y3ljbGljLmdyb3d0aC5vZCRUaW1lW3doaWNoKGN5Y2xpYy5ncm93dGgub2QkV1RfMF9BIT0iIildLHk9Y3ljbGljLmdyb3d0aC5vZCRXVF8wX0Fbd2hpY2goY3ljbGljLmdyb3d0aC5vZCRXVF8wX0EhPSIiKV0sY29sPXN0cmFpbi5jb2xvcnNbIldUIl0scGNoPTAsdHlwZT0ibyIseGxhYj0iVGltZSAoaCkiLHlsYWI9Ik9ENjAwIix4bGltPWMoMCw3KSx5bGltPWMoMCwxLjEpLGNleC5heGlzPTEuNSxjZXgubGFiPTEuNSxtYWluPSJbVEVUXT0wIikgI3JlcGxpY2F0ZSBCCnBvaW50cyh4PWN5Y2xpYy5ncm93dGgub2QkVGltZVt3aGljaChjeWNsaWMuZ3Jvd3RoLm9kJFdUXzBfQiE9IiIpXSx5PWN5Y2xpYy5ncm93dGgub2QkV1RfMF9CW3doaWNoKGN5Y2xpYy5ncm93dGgub2QkV1RfMF9CIT0iIildLGNvbD1zdHJhaW4uY29sb3JzWyJXVCJdLHBjaD0xLHR5cGU9Im8iKSAgCiNyZXBsaWNhdGUgQwpwb2ludHMoeD1jeWNsaWMuZ3Jvd3RoLm9kJFRpbWVbd2hpY2goY3ljbGljLmdyb3d0aC5vZCRXVF8wX0MhPSIiKV0seT1jeWNsaWMuZ3Jvd3RoLm9kJFdUXzBfQ1t3aGljaChjeWNsaWMuZ3Jvd3RoLm9kJFdUXzBfQyE9IiIpXSxjb2w9c3RyYWluLmNvbG9yc1siV1QiXSxwY2g9Mix0eXBlPSJvIikgIAojcGxvdCBpbmRpdmlkdWFsIGdyb3d0aCBjdXJ2ZXMgb2YgV1QgRGFyY0EgcmVwbGljYXRlcyBpbiB0ZXRyYWN5Y2xpbmUtZnJlZSBMQgojcmVwbGljYXRlIEEKcG9pbnRzKHg9Y3ljbGljLmdyb3d0aC5vZCRUaW1lW3doaWNoKGN5Y2xpYy5ncm93dGgub2QkV1RhcmNBXzBfQSE9IiIpXSx5PWN5Y2xpYy5ncm93dGgub2QkV1RhcmNBXzBfQVt3aGljaChjeWNsaWMuZ3Jvd3RoLm9kJFdUYXJjQV8wX0EhPSIiKV0sY29sPXN0cmFpbi5jb2xvcnNbIldUYXJjQSJdLHBjaD0wLHR5cGU9Im8iKSAgCiNyZXBsaWNhdGUgQgpwb2ludHMoeD1jeWNsaWMuZ3Jvd3RoLm9kJFRpbWVbd2hpY2goY3ljbGljLmdyb3d0aC5vZCRXVGFyY0FfMF9CIT0iIildLHk9Y3ljbGljLmdyb3d0aC5vZCRXVGFyY0FfMF9CW3doaWNoKGN5Y2xpYy5ncm93dGgub2QkV1RhcmNBXzBfQiE9IiIpXSxjb2w9c3RyYWluLmNvbG9yc1siV1RhcmNBIl0scGNoPTEsdHlwZT0ibyIpICAKI3JlcGxpY2F0ZSBDCnBvaW50cyh4PWN5Y2xpYy5ncm93dGgub2QkVGltZVt3aGljaChjeWNsaWMuZ3Jvd3RoLm9kJFdUYXJjQV8wX0MhPSIiKV0seT1jeWNsaWMuZ3Jvd3RoLm9kJFdUYXJjQV8wX0Nbd2hpY2goY3ljbGljLmdyb3d0aC5vZCRXVGFyY0FfMF9DIT0iIildLGNvbD1zdHJhaW4uY29sb3JzWyJXVGFyY0EiXSxwY2g9Mix0eXBlPSJvIikgIAphYmxpbmUoaD0xLGNvbD0iZGFya2dyZXkiLGx0eT0yKQojcGxvdCBpbmRpdmlkdWFsIGdyb3d0aCBjdXJ2ZXMgb2YgV1QgcmVwbGljYXRlcyBpbiBMQiB3aXRoIDAuNzUgdWcvbWwgb2YgdGV0cmFjeWNsaW5lCiNyZXBsaWNhdGUgQQpwbG90KHg9Y3ljbGljLmdyb3d0aC5vZCRUaW1lW3doaWNoKGN5Y2xpYy5ncm93dGgub2QkV1RfMC43NV9BIT0iIildLHk9Y3ljbGljLmdyb3d0aC5vZCRXVF8wLjc1X0Fbd2hpY2goY3ljbGljLmdyb3d0aC5vZCRXVF8wLjc1X0EhPSIiKV0sY29sPXN0cmFpbi5jb2xvcnNbIldUIl0scGNoPTAsdHlwZT0ibyIseGxhYj0iVGltZSAoaCkiLHlsYWI9Ik9ENjAwIix4bGltPWMoMCwzMCkseWxpbT1jKDAsMS4xKSxjZXguYXhpcz0xLjUsY2V4LmxhYj0xLjUsbWFpbj0iW1RFVF09MC43NSB1Zy9tbCIpICAKI3JlcGxpY2F0ZSBCCnBvaW50cyh4PWN5Y2xpYy5ncm93dGgub2QkVGltZVt3aGljaChjeWNsaWMuZ3Jvd3RoLm9kJFdUXzAuNzVfQiE9IiIpXSx5PWN5Y2xpYy5ncm93dGgub2QkV1RfMC43NV9CW3doaWNoKGN5Y2xpYy5ncm93dGgub2QkV1RfMC43NV9CIT0iIildLGNvbD1zdHJhaW4uY29sb3JzWyJXVCJdLHBjaD0xLHR5cGU9Im8iKSAgCiNyZXBsaWNhdGUgQwpwb2ludHMoeD1jeWNsaWMuZ3Jvd3RoLm9kJFRpbWVbd2hpY2goY3ljbGljLmdyb3d0aC5vZCRXVF8wLjc1X0MhPSIiKV0seT1jeWNsaWMuZ3Jvd3RoLm9kJFdUXzAuNzVfQ1t3aGljaChjeWNsaWMuZ3Jvd3RoLm9kJFdUXzAuNzVfQyE9IiIpXSxjb2w9c3RyYWluLmNvbG9yc1siV1QiXSxwY2g9Mix0eXBlPSJvIikgIAojcGxvdCBpbmRpdmlkdWFsIGdyb3d0aCBjdXJ2ZXMgb2YgV1QgRGFyY0EgcmVwbGljYXRlcyBpbiBMQiB3aXRoIDAuNzUgdWcvbWwKI3JlcGxpY2F0ZSBBCnBvaW50cyh4PWN5Y2xpYy5ncm93dGgub2QkVGltZVt3aGljaChjeWNsaWMuZ3Jvd3RoLm9kJFdUYXJjQV8wLjc1X0EhPSIiKV0seT1jeWNsaWMuZ3Jvd3RoLm9kJFdUYXJjQV8wLjc1X0Fbd2hpY2goY3ljbGljLmdyb3d0aC5vZCRXVGFyY0FfMC43NV9BIT0iIildLGNvbD1zdHJhaW4uY29sb3JzWyJXVGFyY0EiXSxwY2g9MCx0eXBlPSJvIikgIAojcmVwbGljYXRlIEIKcG9pbnRzKHg9Y3ljbGljLmdyb3d0aC5vZCRUaW1lW3doaWNoKGN5Y2xpYy5ncm93dGgub2QkV1RhcmNBXzAuNzVfQiE9IiIpXSx5PWN5Y2xpYy5ncm93dGgub2QkV1RhcmNBXzAuNzVfQlt3aGljaChjeWNsaWMuZ3Jvd3RoLm9kJFdUYXJjQV8wLjc1X0IhPSIiKV0sY29sPXN0cmFpbi5jb2xvcnNbIldUYXJjQSJdLHBjaD0xLHR5cGU9Im8iKSAgCiNyZXBsaWNhdGUgQwpwb2ludHMoeD1jeWNsaWMuZ3Jvd3RoLm9kJFRpbWVbd2hpY2goY3ljbGljLmdyb3d0aC5vZCRXVGFyY0FfMC43NV9DIT0iIildLHk9Y3ljbGljLmdyb3d0aC5vZCRXVGFyY0FfMC43NV9DW3doaWNoKGN5Y2xpYy5ncm93dGgub2QkV1RhcmNBXzAuNzVfQyE9IiIpXSxjb2w9c3RyYWluLmNvbG9yc1siV1RhcmNBIl0scGNoPTIsdHlwZT0ibyIpICAKYWJsaW5lKGg9MSxjb2w9ImRhcmtncmV5IixsdHk9MikKI2FkZCBsZWdlbmQKcGxvdC5uZXcoKQpsZWdlbmQoImNlbnRlciIsY29sPXN0cmFpbi5jb2xvcnNbYygiV1QiLCJXVGFyY0EiKV0sbGVnZW5kID0gYygiV1QiLGV4cHJlc3Npb24ocGFzdGUoIldUICIsRGVsdGEsICJhcmNBIikpKSxsdHk9MSkKYGBgCjQuNSBGaWcuIDRECmBgYHtyfQojcnVuIEdyb3d0aGN1cnZlciBhbmFseXNpcyBhZ2FpbgppbnB1dC5tYXRyaXguZ3Jvd3RoY3VydmVyPC1hcy5kYXRhLmZyYW1lKGNiaW5kKHRpbWUuZGF0YSxncm93dGguZGF0YS5ub3JtYWxpemVkKSkKI3JlbmFtZSBjb2x1bW4gd2l0aCB0aW1lIGluZm9ybWF0aW9uCmNvbG5hbWVzKGlucHV0Lm1hdHJpeC5ncm93dGhjdXJ2ZXIpWzFdPC0idGltZSIKI3J1biBHcm93dGhjdXJ2ZXIgZm9yIHRoZSBmdWxsIDQ4aApncm93dGhjdXJ2ZXIub3V0cHV0IDwtIFN1bW1hcml6ZUdyb3d0aEJ5UGxhdGUoaW5wdXQubWF0cml4Lmdyb3d0aGN1cnZlcikKI2NyZWF0ZSBGaWcuIDREIChsZWZ0IHBhbmVsKQojZGF0YSBmcmFtZSB3aXRoIEdyb3d0aGN1cnZlci1lc3RpbWF0ZWQgQVVDcyBvZiBUZXRSLCBUZXRSIERhcmNBIGFuZCBUZXRSIERhcmNBICsgcFJCMy1hcmNBIChlcGlzb21hbCBjb21wbGVtZW50ZWQgc3RyYWluKQphdWMuZGY8LWMoKQojZXh0cmFjdCBBVUMgdmFsdWVzIG9mIFRldFIgZnJvbSBHcm93dGhjdXJ2ZXIgb3V0cHV0CnRldFIuc2FtcGxlcy5wb3NpdGlvbnM8LWdyZXAoIlRldFJfIixncm93dGhjdXJ2ZXIub3V0cHV0Wywic2FtcGxlIl0pCnRldFIuYXVjPC1ncm93dGhjdXJ2ZXIub3V0cHV0W3RldFIuc2FtcGxlcy5wb3NpdGlvbnMsImF1Y19lIl0KbmFtZXModGV0Ui5hdWMpPC1ncm93dGhjdXJ2ZXIub3V0cHV0W3RldFIuc2FtcGxlcy5wb3NpdGlvbnMsInNhbXBsZSJdCiNjb21wdXRlIG1lYW4gYW5kIFNEIGZvciBBVUMgdmFsdWVzIGZvciBlYWNoIHRldHJhY3ljbGluZSBjb25jZW50cmF0aW9uCnRlbXBvcmFsLmF1Yy5tYXRyaXg8LWNiaW5kKHNhcHBseSgxOjcsZnVuY3Rpb24oeCl7bWVhbih0ZXRSLmF1Y1soKHgtMSkqNikrMTo2XSl9KSwKICAgICAgICAgICAgICAgICAgICAgICAgICBzYXBwbHkoMTo3LGZ1bmN0aW9uKHgpe3NkKHRldFIuYXVjWygoeC0xKSo2KSsxOjZdKX0pKQojYWRkIHZhbHVlcyB0byBkYXRhIGZyYW1lIAphdWMuZGY8LXJiaW5kKGF1Yy5kZix0ZW1wb3JhbC5hdWMubWF0cml4KQojZXh0cmFjdCBBVUMgdmFsdWVzIG9mIFRldFIgRGFyY0EgZnJvbSBHcm93dGhjdXJ2ZXIgb3V0cHV0CnRldFIuYXJjQS5zYW1wbGVzLnBvc2l0aW9uczwtZ3JlcCgiVGV0UmFyY0FfIixncm93dGhjdXJ2ZXIub3V0cHV0Wywic2FtcGxlIl0pCnRldFIuYXJjQS5hdWM8LWdyb3d0aGN1cnZlci5vdXRwdXRbdGV0Ui5hcmNBLnNhbXBsZXMucG9zaXRpb25zLCJhdWNfZSJdCm5hbWVzKHRldFIuYXJjQS5hdWMpPC1ncm93dGhjdXJ2ZXIub3V0cHV0W3RldFIuYXJjQS5zYW1wbGVzLnBvc2l0aW9ucywic2FtcGxlIl0KI2NvbXB1dGUgbWVhbiBhbmQgU0QgZm9yIEFVQyB2YWx1ZXMgZm9yIGVhY2ggdGV0cmFjeWNsaW5lIGNvbmNlbnRyYXRpb24KdGVtcG9yYWwuYXVjLm1hdHJpeDwtY2JpbmQoc2FwcGx5KDE6NyxmdW5jdGlvbih4KXttZWFuKHRldFIuYXJjQS5hdWNbKCh4LTEpKjYpKzE6Nl0pfSksCiAgICAgICAgICAgICAgICAgICBzYXBwbHkoMTo3LGZ1bmN0aW9uKHgpe3NkKHRldFIuYXJjQS5hdWNbKCh4LTEpKjYpKzE6Nl0pfSkpCiNhZGQgdmFsdWVzIHRvIGRhdGEgZnJhbWUgCmF1Yy5kZjwtcmJpbmQoYXVjLmRmLHRlbXBvcmFsLmF1Yy5tYXRyaXgpCiNleHRyYWN0IEFVQyB2YWx1ZXMgb2YgVGV0UiBEYXJjQSArIHBSQjMtYXJjQSBmcm9tIEdyb3d0aGN1cnZlciBvdXRwdXQKdGV0Ui5hcmNBLnBSQjMuc2FtcGxlcy5wb3NpdGlvbnM8LWdyZXAoInBSQjNhcmNBXyIsZ3Jvd3RoY3VydmVyLm91dHB1dFssInNhbXBsZSJdKQp0ZXRSLmFyY0EucFJCMy5hdWM8LWdyb3d0aGN1cnZlci5vdXRwdXRbdGV0Ui5hcmNBLnBSQjMuc2FtcGxlcy5wb3NpdGlvbnMsImF1Y19lIl0KbmFtZXModGV0Ui5hcmNBLnBSQjMuYXVjKTwtZ3Jvd3RoY3VydmVyLm91dHB1dFt0ZXRSLmFyY0EucFJCMy5zYW1wbGVzLnBvc2l0aW9ucywic2FtcGxlIl0KI2NvbXB1dGUgbWVhbiBhbmQgU0QgZm9yIEFVQyB2YWx1ZXMgZm9yIGVhY2ggdGV0cmFjeWNsaW5lIGNvbmNlbnRyYXRpb24KdGVtcG9yYWwuYXVjLm1hdHJpeDwtY2JpbmQoc2FwcGx5KDE6NyxmdW5jdGlvbih4KXttZWFuKHRldFIuYXJjQS5wUkIzLmF1Y1soKHgtMSkqNikrMTo2XSl9KSwKICAgICAgICAgICAgICAgICAgIHNhcHBseSgxOjcsZnVuY3Rpb24oeCl7c2QodGV0Ui5hcmNBLnBSQjMuYXVjWygoeC0xKSo2KSsxOjZdKX0pKQojYWRkIHZhbHVlcyB0byBkYXRhIGZyYW1lIAphdWMuZGY8LXJiaW5kKGF1Yy5kZix0ZW1wb3JhbC5hdWMubWF0cml4KQojbWFrZSBzdXJlIGRhdGEgZnJhbWUgZm9ybWF0IGlzIGNvcnJlY3QKYXVjLnRldC5jb25jZW50cmF0aW9uczwtZmFjdG9yKHJlcCh0ZXRyYWN5Y2xpbmUuY29uY2VudHJhdGlvbnMsMyksbGV2ZWxzID0gc2VxKDAsMjQsYnk9NCkpCmF1Yy5zdHJhaW5zPC1mYWN0b3IocmVwKGMoIlRldFIiLCJUZXRSYXJjQSIsInBSQjNhcmNBIiksZWFjaD03KSxsZXZlbHMgPSBjKCJUZXRSIiwiVGV0UmFyY0EiLCJwUkIzYXJjQSIpKQojYWRkIGNvbHVtbnMgd2l0aCB0ZXRyYWN5Y2xpbmUgY29uY2VudHJhdGlvbiBhbmQgc3RyYWluIGluZm9ybWF0aW9uCmF1Yy5kZjwtY2JpbmQoYXMuZGF0YS5mcmFtZShhdWMuZGYpLGF1Yy50ZXQuY29uY2VudHJhdGlvbnMsYXVjLnN0cmFpbnMpCmNvbG5hbWVzKGF1Yy5kZik8LWMoImF1YyIsInNkIiwiQ29uY2VudHJhdGlvbiIsIlN0cmFpbiIpCiNjcmVhdGUgZ2dwbG90IG9iamVjdApwbG90LmF1Yy5lc3RpbWF0ZXM8LSBnZ3Bsb3QoYXVjLmRmLCBhZXMoeD1Db25jZW50cmF0aW9uLHk9YXVjLCBncm91cD1TdHJhaW4sY29sb3VyPVN0cmFpbikpICsKICBnZW9tX2xpbmUoKSArCiAgZ2VvbV9wb2ludCgpKwogIGdlb21fZXJyb3JiYXIoYWVzKHltaW49YXVjLXNkLCB5bWF4PWF1YytzZCksIHdpZHRoPTAuNzUpICsgdGhlbWVfY2xhc3NpYygpICt0aGVtZShhc3BlY3QucmF0aW8gPSAxKQojc2ltaWxhciBhbmFseXNpcyBmb3IgbGFnIHBoYXNlIHByb3h5IChGaWcuIDREIHJpZ2h0IHBhbmVsKQojcG9pbnQgb2YgaW5mbGVjdGlvbiAoaWUsIHRpbWUgcG9pbnQgZm9yIDEvMiBtYXggT0QpIHdhcyB1c2VkIGFzIGEgcHJveHkgZm9yIGxhZyBwaGFzZQojZGF0YSBmcmFtZSB3aXRoIEdyb3d0aGN1cnZlci1lc3RpbWF0ZWQgbGFnIHBoYXNlIHByb3h5IG9mIFRldFIsIFRldFIgRGFyY0EgYW5kIFRldFIgRGFyY0EgKyBwUkIzLWFyY0EgKGVwaXNvbWFsIGNvbXBsZW1lbnRlZCBzdHJhaW4pCmxhZy5kZjwtYygpCiNleHRyYWN0IHBvaW50IG9mIGluZmxlY3Rpb24gdmFsdWVzIG9mIFRldFIgZnJvbSBHcm93dGhjdXJ2ZXIgb3V0cHV0CnRldFIubGFnPC1ncm93dGhjdXJ2ZXIub3V0cHV0W3RldFIuc2FtcGxlcy5wb3NpdGlvbnMsInRfbWlkIl0KbmFtZXModGV0Ui5sYWcpPC1ncm93dGhjdXJ2ZXIub3V0cHV0W3RldFIuc2FtcGxlcy5wb3NpdGlvbnMsInNhbXBsZSJdCiNjb21wdXRlIG1lYW4gYW5kIFNEIGZvciBpbmZsZWN0aW9uIHBvaW50IHZhbHVlcyBmb3IgZWFjaCB0ZXRyYWN5Y2xpbmUgY29uY2VudHJhdGlvbgp0ZW1wb3JhbC5sYWcubWF0cml4PC1jYmluZChzYXBwbHkoMTo3LGZ1bmN0aW9uKHgpe21lYW4odGV0Ui5sYWdbKCh4LTEpKjYpKzE6Nl0pfSksCiAgICAgICAgICAgICAgICAgICBzYXBwbHkoMTo3LGZ1bmN0aW9uKHgpe3NkKHRldFIubGFnWygoeC0xKSo2KSsxOjZdKX0pKQojYWRkIHZhbHVlcyB0byBkYXRhIGZyYW1lIApsYWcuZGY8LXJiaW5kKGxhZy5kZix0ZW1wb3JhbC5sYWcubWF0cml4KQojZXh0cmFjdCBwb2ludCBvZiBpbmZsZWN0aW9uIHZhbHVlcyBvZiBUZXRSIERhcmNBIGZyb20gR3Jvd3RoY3VydmVyIG91dHB1dAp0ZXRSLmFyY0EubGFnPC1ncm93dGhjdXJ2ZXIub3V0cHV0W3RldFIuYXJjQS5zYW1wbGVzLnBvc2l0aW9ucywidF9taWQiXQpuYW1lcyh0ZXRSLmFyY0EubGFnKTwtZ3Jvd3RoY3VydmVyLm91dHB1dFt0ZXRSLmFyY0Euc2FtcGxlcy5wb3NpdGlvbnMsInNhbXBsZSJdCiNjb21wdXRlIG1lYW4gYW5kIFNEIGZvciBpbmZsZWN0aW9uIHBvaW50IHZhbHVlcyBmb3IgZWFjaCB0ZXRyYWN5Y2xpbmUgY29uY2VudHJhdGlvbgp0ZW1wb3JhbC5sYWcubWF0cml4PC1jYmluZChzYXBwbHkoMTo3LGZ1bmN0aW9uKHgpe21lYW4odGV0Ui5hcmNBLmxhZ1soKHgtMSkqNikrMTo2XSl9KSwKICAgICAgICAgICAgICAgICAgIHNhcHBseSgxOjcsZnVuY3Rpb24oeCl7c2QodGV0Ui5hcmNBLmxhZ1soKHgtMSkqNikrMTo2XSl9KSkKI2FkZCB2YWx1ZXMgdG8gZGF0YSBmcmFtZSAKbGFnLmRmPC1yYmluZChsYWcuZGYsdGVtcG9yYWwubGFnLm1hdHJpeCkKI2V4dHJhY3QgcG9pbnQgb2YgaW5mbGVjdGlvbiB2YWx1ZXMgb2YgVGV0UiBEYXJjQSArIHBSQjMtYXJjQSBmcm9tIEdyb3d0aGN1cnZlciBvdXRwdXQKdGV0Ui5hcmNBLnBSQjMubGFnPC1ncm93dGhjdXJ2ZXIub3V0cHV0W3RldFIuYXJjQS5wUkIzLnNhbXBsZXMucG9zaXRpb25zLCJ0X21pZCJdCnRlbXBvcmFsLmxhZy5tYXRyaXg8LWNiaW5kKHNhcHBseSgxOjcsZnVuY3Rpb24oeCl7bWVhbih0ZXRSLmFyY0EucFJCMy5sYWdbKCh4LTEpKjYpKzE6Nl0pfSksCiAgICAgICAgICAgICAgICAgICBzYXBwbHkoMTo3LGZ1bmN0aW9uKHgpe3NkKHRldFIuYXJjQS5wUkIzLmxhZ1soKHgtMSkqNikrMTo2XSl9KSkKI2FkZCB2YWx1ZXMgdG8gZGF0YSBmcmFtZSAKbGFnLmRmPC1yYmluZChsYWcuZGYsdGVtcG9yYWwubGFnLm1hdHJpeCkKI2FkZCBjb2x1bW5zIHdpdGggdGV0cmFjeWNsaW5lIGNvbmNlbnRyYXRpb24gYW5kIHN0cmFpbiBpbmZvcm1hdGlvbgpsYWcuZGY8LWNiaW5kKGFzLmRhdGEuZnJhbWUobGFnLmRmKSxhdWMudGV0LmNvbmNlbnRyYXRpb25zLGF1Yy5zdHJhaW5zKQpjb2xuYW1lcyhsYWcuZGYpPC1jKCJsYWciLCJzZCIsIkNvbmNlbnRyYXRpb24iLCJTdHJhaW4iKQojaWYgZXN0aW1hdGVkIHBvaW50IG9mIGluZmxlY3Rpb24gd2FzID4gNDhoLCB0aGVuIHRoZSB2YWx1ZSB3YXMgc2V0IHRvIDQ4CmxhZy5kZiRzZFt3aGljaChsYWcuZGYkbGFnPjQ4KV08LTAKbGFnLmRmJGxhZ1t3aGljaChsYWcuZGYkbGFnPjQ4KV08LTQ4CiNjcmVhdGUgZ2dwbG90IG9iamVjdApwbG90LmxhZy5lc3RpbWF0ZXM8LSBnZ3Bsb3QobGFnLmRmLCBhZXMoeD1Db25jZW50cmF0aW9uLHk9bGFnLCBncm91cD1TdHJhaW4sY29sb3VyPVN0cmFpbikpICsKICBnZW9tX2xpbmUoKSArCiAgZ2VvbV9wb2ludCgpKwogIGdlb21fZXJyb3JiYXIoYWVzKHltaW49bGFnLXNkLCB5bWF4PWxhZytzZCksIHdpZHRoPTAuNzUpICsgdGhlbWVfY2xhc3NpYygpICt0aGVtZShhc3BlY3QucmF0aW8gPSAxKQojY3JlYXRlIEZpZy4gNEQKZ3JpZC5hcnJhbmdlKHBsb3QuYXVjLmVzdGltYXRlcyArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9c3RyYWluLmNvbG9yc1szOjVdKSsKICAgICAgICB0aGVtZShheGlzLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTApLCBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTApLAogICAgICAgICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAiYmxhY2siLCBmaWxsPU5BLCBzaXplPTAuNSkpIAogICAgICArIHhsYWIoIltURVRdKHVnL21sKSIpK3lsYWIoIkFVQyIpK2dndGl0bGUoIkZpZy4gNEQiKSwgcGxvdC5sYWcuZXN0aW1hdGVzICsgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1zdHJhaW4uY29sb3JzWzM6NV0pKwogICAgICAgIHRoZW1lKGF4aXMudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMCksIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xMCksCiAgICAgICAgICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJibGFjayIsIGZpbGw9TkEsIHNpemU9MC41KSkKICAgICAgKyB4bGFiKCJbVEVUXSh1Zy9tbCkiKSt5bGFiKCJ+TGFnIHBoYXNlIChoKSIpLCBucm93PTEpCmBgYAo0LjYgRmlnLiA0RSAKYGBge3J9CiNyYXcgYW5kIHByb2Nlc3NlZCBkYXRhIGlzIGF2YWlsYWJsZSBpbiB0aGUgIkRhdGEvTkFESF9OQUQvbmFkaF9uYWRfbWVhc3VyZW1lbnQueGxzeCIgZmlsZQojcmVzdWx0cyBhcmUgdGhlIGNvbXBpbGF0aW9uIG9mIHR3byBpbmRlcGVuZGVudCBleHBlcmltZW50cwojaW4gZWFjaCBleHBlcmltZW50LCB0aGUgTkFESCBhbmQgTkFEIGNvbmNlbnRyYXRpb25zIG9mIFdULCBXVCBEYXJjQSwgVGV0UiBhbmQgVGV0UiBEYXJjQSB3ZXJlIG1lYXN1cmVkIHdpdGggYW5kIHdpdGhvdXQgdGV0cmFjeWNsaW5lICgwLjc1IHVnL21sIGZvciBXVCBhbmQgV1QgRGFyY0EsIGFuZCA0IHVnL21sIGZvciBUZXRSIGFuZCBUZXRSIERhcmNBKQojTkFESC9OQUQgcmF0aW9zIGluIDFzdCBleHBlcmltZW50LCBjdWx0dXJlcyB3aXRob3V0IHRldHJhY3ljbGluZQp3dC5uby50ZXRyYWN5Y2xpbmUuZXhwdDE8LWMoMC4wMjU3MzUyOTQsMC4wNTI0MzQ0NTcsMC4wNDY4NzUpCnd0LmFyY0Eubm8udGV0cmFjeWNsaW5lLmV4cHQxPC1jKDAuMDcxOTE3ODA4LDAuMDgxNjMyNjUzLDAuMDcwMTEwNzAxKQp0ZXRSLm5vLnRldHJhY3ljbGluZS5leHB0MTwtYygwLjA3NTExNzM3MSwwLjA4MTU0NTA2NCwwLjA0MzcxNTg0NykKdGV0Ui5hcmNBLm5vLnRldHJhY3ljbGluZS5leHB0MTwtYygwLjM4MDY0NTE2MSwwLjEyOTk0MzUwMywwLjE5Nzc0MDExMykKI05BREgvTkFEIHJhdGlvcyBpbiAxc3QgZXhwZXJpbWVudCwgY3VsdHVyZXMgd2l0aCB0ZXRyYWN5Y2xpbmUKd3Qud2l0aC50ZXRyYWN5Y2xpbmUuZXhwdDE8LWMoMC4wNTUyNDg2MTg3OCwwLjAyMDMyNTIwMzI1LDAuMDI5MjY4MjkyNjgpCnd0LmFyY0Eud2l0aC50ZXRyYWN5Y2xpbmUuZXhwdDE8LWMoMC4wNDU0NTQ1NDU0NSwwLjAzNTE3NTg3OTQsMC4wNTgwMzU3MTQyOSkKdGV0Ui53aXRoLnRldHJhY3ljbGluZS5leHB0MTwtYygwLjE2MzE5NDQ0NDQsMC4xOTM2NTA3OTM3LDAuMTAzMjI1ODA2NSkKdGV0Ui5hcmNBLndpdGgudGV0cmFjeWNsaW5lLmV4cHQxPC1jKDAuMTMwMjkzMTU5NiwwLjMzMTI4ODM0MzYsMC4yMjE4MTgxODE4KQojTkFESC9OQUQgcmF0aW9zIGluIDJuZCBleHBlcmltZW50LCBjdWx0dXJlcyB3aXRob3V0IHRldHJhY3ljbGluZQp3dC5uby50ZXRyYWN5Y2xpbmUuZXhwdDI8LWMoMC4wNTI4MTY5MDEsMC4wNjkyMDQxNTIpCnd0LmFyY0Eubm8udGV0cmFjeWNsaW5lLmV4cHQyPC1jKCkKdGV0Ui5uby50ZXRyYWN5Y2xpbmUuZXhwdDI8LWMoMC4wNjE4NTU2NywwLjA1MjYzMTU3OSkKdGV0Ui5hcmNBLm5vLnRldHJhY3ljbGluZS5leHB0MjwtYygwLjA5MDQyNTUzMiwwLjE0Mjg1NzE0MywwLjExNDA5Mzk2KQojTkFESC9OQUQgcmF0aW9zIGluIDJuZCBleHBlcmltZW50LCBjdWx0dXJlcyB3aXRoIHRldHJhY3ljbGluZQp3dC53aXRoLnRldHJhY3ljbGluZS5leHB0MjwtYygwLjA3NDA3NDA3NCwwLjA1MDQ1ODcxNikKd3QuYXJjQS53aXRoLnRldHJhY3ljbGluZS5leHB0MjwtYygwLjA0NTgwMTUyNywwLjAzNjM2MzYzNikKdGV0Ui53aXRoLnRldHJhY3ljbGluZS5leHB0MjwtYygwLjExNjkzNTQ4NCwwLjEyMDYyMjU2OCkKdGV0Ui5hcmNBLndpdGgudGV0cmFjeWNsaW5lLmV4cHQyPC1jKDAuMDkyMDUwMjA5LDAuMDU1NzkzOTkxLDAuMDg5NjIyNjQyKQojY29tYmluZSBkYXRhIGZyb20gdGhlIHR3byBleHBlcmltZW50cwojY3VsdHVyZXMgd2l0aG91dCB0ZXRyYWN5Y2xpbmUKd3Qubm8udGV0cmFjeWNsaW5lPC1jKHd0Lm5vLnRldHJhY3ljbGluZS5leHB0MSx3dC5uby50ZXRyYWN5Y2xpbmUuZXhwdDIpCnd0LmFyY0Eubm8udGV0cmFjeWNsaW5lPC1jKHd0LmFyY0Eubm8udGV0cmFjeWNsaW5lLmV4cHQxLHd0LmFyY0Eubm8udGV0cmFjeWNsaW5lLmV4cHQyKQp0ZXRSLm5vLnRldHJhY3ljbGluZTwtYyh0ZXRSLm5vLnRldHJhY3ljbGluZS5leHB0MSx0ZXRSLm5vLnRldHJhY3ljbGluZS5leHB0MikKdGV0Ui5hcmNBLm5vLnRldHJhY3ljbGluZTwtYyh0ZXRSLmFyY0Eubm8udGV0cmFjeWNsaW5lLmV4cHQxLHRldFIuYXJjQS5uby50ZXRyYWN5Y2xpbmUuZXhwdDIpCiNjdWx0dXJlcyB3aXRoIHRldHJhY3ljbGluZQp3dC53aXRoLnRldHJhY3ljbGluZTwtYyh3dC53aXRoLnRldHJhY3ljbGluZS5leHB0MSx3dC53aXRoLnRldHJhY3ljbGluZS5leHB0MikKd3QuYXJjQS53aXRoLnRldHJhY3ljbGluZTwtYyh3dC5hcmNBLndpdGgudGV0cmFjeWNsaW5lLmV4cHQxLHd0LmFyY0Eud2l0aC50ZXRyYWN5Y2xpbmUuZXhwdDIpCnRldFIud2l0aC50ZXRyYWN5Y2xpbmU8LWModGV0Ui53aXRoLnRldHJhY3ljbGluZS5leHB0MSx0ZXRSLndpdGgudGV0cmFjeWNsaW5lLmV4cHQyKQp0ZXRSLmFyY0Eud2l0aC50ZXRyYWN5Y2xpbmU8LWModGV0Ui5hcmNBLndpdGgudGV0cmFjeWNsaW5lLmV4cHQxLHRldFIuYXJjQS53aXRoLnRldHJhY3ljbGluZS5leHB0MikKYm94cGxvdCh3dC5uby50ZXRyYWN5Y2xpbmUsd3Qud2l0aC50ZXRyYWN5Y2xpbmUsd3QuYXJjQS5uby50ZXRyYWN5Y2xpbmUsd3QuYXJjQS53aXRoLnRldHJhY3ljbGluZSwKICAgICAgICB0ZXRSLm5vLnRldHJhY3ljbGluZSx0ZXRSLndpdGgudGV0cmFjeWNsaW5lLHRldFIuYXJjQS5uby50ZXRyYWN5Y2xpbmUsdGV0Ui5hcmNBLndpdGgudGV0cmFjeWNsaW5lLCBjb2w9cmVwKHN0cmFpbi5jb2xvcnNbMTo0XSxlYWNoPTIpLAogICAgICAgIG5hbWVzPXBhc3RlKHJlcChjKCJXVCIsIldUIGFyY0EiLCJUZXRSIiwiVGV0UiBhcmNBIiksZWFjaD0yKSxyZXAoYygiKC0pIiwiKCspIiksNCksc2VwPSIiKSxsYXM9MiwKICAgICAgICB5bGFiPSJOQURIL05BRCIseWxpbT1jKDAsMC40KSxjZXg9LjcsY2V4LmxhYj0uNywgY2V4LmF4aXM9LjcsbWFpbj0iRmlnLiA0RSIpCiNULXRlc3Qgd2l0aCByZXNwZWN0IHRvIHd0KC1URVQpCnByaW50KHBhc3RlKCJULXRlc3QgcC12YWx1ZSBmb3IgV1QoLSkgdnMgV1QgYXJjQSgtKToiLHQudGVzdCh3dC5uby50ZXRyYWN5Y2xpbmUsd3QuYXJjQS5uby50ZXRyYWN5Y2xpbmUpJHAudmFsdWUsc2VwPSIiKSkKcHJpbnQocGFzdGUoIlQtdGVzdCBwLXZhbHVlIGZvciBXVCgtKSB2cyBUZXRSKC0pOiIsdC50ZXN0KHd0Lm5vLnRldHJhY3ljbGluZSx0ZXRSLm5vLnRldHJhY3ljbGluZSkkcC52YWx1ZSxzZXA9IiIpKQpwcmludChwYXN0ZSgiVC10ZXN0IHAtdmFsdWUgZm9yIFdUKC0pIHZzIFRldFIgYXJjQSgtKToiLHQudGVzdCh3dC5uby50ZXRyYWN5Y2xpbmUsdGV0Ui5hcmNBLm5vLnRldHJhY3ljbGluZSkkcC52YWx1ZSxzZXA9IiIpKQojVC10ZXN0ICgtVEVUKSB2cyAoK1RFVCkgZm9yIGVhY2ggc3RyYWluCnByaW50KHBhc3RlKCJULXRlc3QgcC12YWx1ZSBmb3IgV1QoKykgdnMgV1QoLSk6Iix0LnRlc3Qod3Qubm8udGV0cmFjeWNsaW5lLHd0LndpdGgudGV0cmFjeWNsaW5lKSRwLnZhbHVlLHNlcD0iIikpCnByaW50KHBhc3RlKCJULXRlc3QgcC12YWx1ZSBmb3IgV1QgYXJjQSgrKSB2cyBXVCBhcmNBKC0pOiIsdC50ZXN0KHd0LmFyY0Eubm8udGV0cmFjeWNsaW5lLHd0LmFyY0Eud2l0aC50ZXRyYWN5Y2xpbmUpJHAudmFsdWUsc2VwPSIiKSkKcHJpbnQocGFzdGUoIlQtdGVzdCBwLXZhbHVlIGZvciBUZXRSKCspIHZzIFRldFIoLSk6Iix0LnRlc3QodGV0Ui5uby50ZXRyYWN5Y2xpbmUsdGV0Ui53aXRoLnRldHJhY3ljbGluZSkkcC52YWx1ZSxzZXA9IiIpKQpwcmludChwYXN0ZSgiVC10ZXN0IHAtdmFsdWUgZm9yIFRldFIgYXJjQSgrKSB2cyBUZXRSIGFyY0EoLSk6Iix0LnRlc3QodGV0Ui5hcmNBLm5vLnRldHJhY3ljbGluZSx0ZXRSLmFyY0Eud2l0aC50ZXRyYWN5Y2xpbmUpJHAudmFsdWUsc2VwPSIiKSkKYGBgCjUuMSBGaWcuIDVBCmBgYHtyfQojcmVhZCBtZXRhYm9sb21lIHNpbWlsYXJpdHkgbWF0cml4IGZyb20gQ2FtcG9zICYgWmFtcGllcmkgMjAxOSAoTW9sZWN1bGFyIGNlbGwtVGFibGUgUzMpCnNpbWlsYXJpdHkubWF0cml4PC1yZWFkLmNzdigiLi4vRGF0YS9NZXRhYm9saWNfcHJvZmlsZXMvQ2FtcG9zX1phbXBpZXJpX2RhdGEvZHJ1Z19nZW5lX3NpbWlsYXJpdHlfbWF0cml4LmNzdiIscm93Lm5hbWVzPTEpCiNyZWFkIG1hdHJpeCB3aXRoIHAtdmFsdWVzIGZvciBtZXRhYm9saWMgcHJvZmlsZSBzaW1pbGFyaXR5IGZyb20gQ2FtcG9zICYgWmFtcGllcmkgMjAxOSAoTW9sZWN1bGFyIGNlbGwtVGFibGUgUzMpCnB2YWx1ZS5tYXRyaXg8LXJlYWQuY3N2KCIuLi9EYXRhL01ldGFib2xpY19wcm9maWxlcy9DYW1wb3NfWmFtcGllcmlfZGF0YS9kcnVnX2dlbmVfc2ltaWxhcml0eV9wdmFsdWUuY3N2Iixyb3cubmFtZXM9MSkKI2dlbmVyYXRlIEZpZy4gNUEKcGxvdCh4PXNpbWlsYXJpdHkubWF0cml4WywiYXJjQSJdLHk9LTEqbG9nMTAocHZhbHVlLm1hdHJpeFtyb3duYW1lcyhzaW1pbGFyaXR5Lm1hdHJpeCksImFyY0EiXSkseGxhYj0iRHJ1ZyB0cmVhdG1lbnQtYXJjQSBLTyBzaW1pbGFyaXR5Iix5bGFiPSItbG9nMTAgcC12YWx1ZSIsIG1haW49IkZpZy4gNUEiKQojaGlnaGxpZ2h0IHRoZSB0d28gdHJlYXRtZW50cyBtb3JlIHNpbWlsYXIgdG8gdGhlIGFyY0EgZGVsZXRpb24KcG9pbnRzKHg9c2ltaWxhcml0eS5tYXRyaXhbZ3JlcCgiQ2VmcGlyYW1pZGUiLHJvd25hbWVzKHNpbWlsYXJpdHkubWF0cml4KSksImFyY0EiXSx5PS0xKmxvZzEwKHB2YWx1ZS5tYXRyaXhbZ3JlcCgiQ2VmcGlyYW1pZGUiLHJvd25hbWVzKHB2YWx1ZS5tYXRyaXgpKSwiYXJjQSJdKSxjb2w9InJlZCIscGNoPTE5KQp0ZXh0KHg9c2ltaWxhcml0eS5tYXRyaXhbZ3JlcCgiQ2VmcGlyYW1pZGUiLHJvd25hbWVzKHNpbWlsYXJpdHkubWF0cml4KSksImFyY0EiXS0wLjAyLHk9LTEqbG9nMTAocHZhbHVlLm1hdHJpeFtncmVwKCJDZWZwaXJhbWlkZSIscm93bmFtZXMocHZhbHVlLm1hdHJpeCkpLCJhcmNBIl0pLCJDZWZwaXJhbWlkZSIpCnBvaW50cyh4PXNpbWlsYXJpdHkubWF0cml4W2dyZXAoIlNlcnRyYWxpbmUiLHJvd25hbWVzKHNpbWlsYXJpdHkubWF0cml4KSksImFyY0EiXSx5PS0xKmxvZzEwKHB2YWx1ZS5tYXRyaXhbZ3JlcCgiU2VydHJhbGluZSIscm93bmFtZXMocHZhbHVlLm1hdHJpeCkpLCJhcmNBIl0pLGNvbD0iZGFya2JsdWUiLHBjaD0xOSkKdGV4dCh4PXNpbWlsYXJpdHkubWF0cml4W2dyZXAoIlNlcnRyYWxpbmUiLHJvd25hbWVzKHNpbWlsYXJpdHkubWF0cml4KSksImFyY0EiXSx5PS0xKmxvZzEwKHB2YWx1ZS5tYXRyaXhbZ3JlcCgiU2VydHJhbGluZSIscm93bmFtZXMocHZhbHVlLm1hdHJpeCkpLCJhcmNBIl0pKzAuMywiU2VydHJhbGluZSIpCiNjaGVjayBwb3NpdGlvbiBvZiBhcmNBIEtPIG1ldGFib2xpYyBwcm9maWxlIHdpdGhpbiByYW5raW5nICBvZiBhbGwgZ2VuZSBkZWxldGlvbnMgZm9yIHRoZSB0b3AgMiBjb21wb3VuZHMKYXJjQS5zZXJ0cmFsaW5lLnJhbmtpbmc8LWxlbmd0aCh3aGljaChhcy5udW1lcmljKHNpbWlsYXJpdHkubWF0cml4WyJTZXJ0cmFsaW5lIixdKSA+IHNpbWlsYXJpdHkubWF0cml4WyJTZXJ0cmFsaW5lIiwiYXJjQSJdKSkKcHJpbnQocGFzdGUoIlBvc2l0aW9uIG9mIGFyY0EgZGVsZXRpb24gaW4gc2ltaWxhcml0eSByYW5raW5nIHdpdGggcmVzcGVjdCB0byBTZXJ0cmFsaW5lIHRyZWF0bWVudCBwcm9maWxlIHdhczoiLGFyY0Euc2VydHJhbGluZS5yYW5raW5nKzEsIi8iLG5yb3coc2ltaWxhcml0eS5tYXRyaXgpLHNlcD0iIikpCmFyY0EuY2VmcGlyYW1pZGUucmFua2luZzwtbGVuZ3RoKHdoaWNoKGFzLm51bWVyaWMoc2ltaWxhcml0eS5tYXRyaXhbIkNlZnBpcmFtaWRlIixdKSA+IHNpbWlsYXJpdHkubWF0cml4WyJDZWZwaXJhbWlkZSIsImFyY0EiXSkpCnByaW50KHBhc3RlKCJQb3NpdGlvbiBvZiBhcmNBIGRlbGV0aW9uIGluIHNpbWlsYXJpdHkgcmFua2luZyB3aXRoIHJlc3BlY3QgdG8gQ2VmcGlyYW1pZGUgdHJlYXRtZW50IHByb2ZpbGUgd2FzOiIsYXJjQS5jZWZwaXJhbWlkZS5yYW5raW5nKzEsIi8iLG5yb3coc2ltaWxhcml0eS5tYXRyaXgpLHNlcD0iIikpCmBgYAo1LjIgRmlnLiBTNwpgYGB7cn0KI3JlYWQgbWV0YWJvbGljIHByb2ZpbGVzIG9mIHRyZWF0ZWQgRS4gY29saSAoei1zY29yZXMpIAojdGhlIGRhdGFzZXQgY29udGFpbnMgRS4gY29saSBtZXRhYm9saWMgcHJvZmlsZXMgKDk2OSBtZXRhYm9saXRlcykgZHVyaW5nIHRyZWF0bWVudCB3aXRoIDEsMjc5IGNvbXBvdW5kcwojZGF0YSBzb3VyY2VkIGZyb20gQ2FtcG9zICYgWmFtcGllcmkgMjAxOSAoTW9sZWN1bGFyIGNlbGwtVGFibGUgUzEpCnphbXBpZXJpLm1ldGFib2xpYy5wcm9maWxlczwtcmVhZC5jc3YoIi4uL0RhdGEvTWV0YWJvbGljX3Byb2ZpbGVzL0NhbXBvc19aYW1waWVyaV9kYXRhL3pzY29yZXNfbWV0YWJvbGljX3Byb2ZpbGUuY3N2IixoZWFkZXI9VCkKI3Bsb3QgZGlzdHJpYnV0aW9uIG9mIFotc2NvcmVzIGluIHNlcnRyYWxpbmUgdHJlYXRtZW50CnBhcihtZnJvdz1jKDEsMikpCmhpc3QoemFtcGllcmkubWV0YWJvbGljLnByb2ZpbGVzWywiU2VydHJhbGluZSJdLGJyZWFrcz0xMDAseGxhYj0iTWV0YWJvbGl0ZSB6LXNjb3JlIixtYWluPSJTZXJ0cmFsaW5lIHRyZWF0bWVudCIpCiNkZWZpbmUgdGhyZXNob2xkIHRvIGNvbnNpZGVyIGEgbWV0YWJvbGl0ZSBhcyByZXNwb25zaXZlIHRvIHNlcnRyYWxpbmUgKHRvcCAxMCUgYWJzb2x1dGUgdmFsdWUpCnNlcnRyYWxpbmUuenNjb3JlLnRocmVzaG9sZDwtYXMubnVtZXJpYyhxdWFudGlsZShhYnMoemFtcGllcmkubWV0YWJvbGljLnByb2ZpbGVzWywiU2VydHJhbGluZSJdKSwwLjksbmEucm0gPSBUKSkKI2RlZmluZSBtZXRhYm9saXRlcyB3aG9zZSBjb25jZW50cmF0aW9uIHdhcyBhbHRlcmVkIGJ5IHNlcnRyYWxpbmUKc2VydHJhbGluZS50cmVhdG1lbnQuZGlmZmVyZW50aWFsLm1ldGFib2xpdGVzPC16YW1waWVyaS5tZXRhYm9saWMucHJvZmlsZXNbd2hpY2goYWJzKHphbXBpZXJpLm1ldGFib2xpYy5wcm9maWxlc1ssIlNlcnRyYWxpbmUiXSk+PSBzZXJ0cmFsaW5lLnpzY29yZS50aHJlc2hvbGQpLCJNZXRhYm9saXRlX2lkcyJdCiNyZW1vdmUgZHVwbGljYXRpb24Kc2VydHJhbGluZS50cmVhdG1lbnQuZGlmZmVyZW50aWFsLm1ldGFib2xpdGVzPC11bmlxdWUoc2VydHJhbGluZS50cmVhdG1lbnQuZGlmZmVyZW50aWFsLm1ldGFib2xpdGVzKQojcmVtb3ZlIGVtcHR5IGVudHJ5CnNlcnRyYWxpbmUudHJlYXRtZW50LmRpZmZlcmVudGlhbC5tZXRhYm9saXRlczwtYXMudmVjdG9yKHNlcnRyYWxpbmUudHJlYXRtZW50LmRpZmZlcmVudGlhbC5tZXRhYm9saXRlc1stMjZdKQojc3BsaXQgZW50cmllcyB3aXRoIG11bHRpcGxlIEtFR0cgSURzCnNlcnRyYWxpbmUudHJlYXRtZW50LmRpZmZlcmVudGlhbC5tZXRhYm9saXRlczwtc2FwcGx5KDE6bGVuZ3RoKHNlcnRyYWxpbmUudHJlYXRtZW50LmRpZmZlcmVudGlhbC5tZXRhYm9saXRlcyksZnVuY3Rpb24oeCl7c3Ryc3BsaXQoc2VydHJhbGluZS50cmVhdG1lbnQuZGlmZmVyZW50aWFsLm1ldGFib2xpdGVzW3hdLHNwbGl0PSJ+IilbWzFdXX0pCiNzYXZlIGZpbGUgd2l0aCBLRUdHIGlkIG9mIGFsdGVyZWQgbWV0YWJvbGl0ZXMKI3dyaXRlLmNzdihmaWxlPSIuLi9EYXRhL01ldGFib2xpY19wcm9maWxlcy9DYW1wb3NfWmFtcGllcmlfZGF0YS9kaWZmZXJlbnRpYWxfbWV0YWJvbGl0ZXNfc2VydHJhbGluZV8wODMwMjAyMi5jc3YiLGFycmF5KGFzLmNoYXJhY3Rlcih1bmxpc3Qoc2VydHJhbGluZS50cmVhdG1lbnQuZGlmZmVyZW50aWFsLm1ldGFib2xpdGVzKSkpKQojcmVwZWF0IGFuYWx5c2lzIGZvciBjZWZwaXJhbWlkZSBkYXRhCiNwbG90IGRpc3RyaWJ1dGlvbiBvZiBaLXNjb3JlcyBpbiBjZWZwaXJhbWlkZSB0cmVhdG1lbnQKaGlzdCh6YW1waWVyaS5tZXRhYm9saWMucHJvZmlsZXNbLCJDZWZwaXJhbWlkZSJdLGJyZWFrcz0xMDAseGxhYj0iTWV0YWJvbGl0ZSB6LXNjb3JlIixtYWluPSJDZWZwaXJhbWlkZSB0cmVhdG1lbnQiKQojZGVmaW5lIHRocmVzaG9sZCB0byBjb25zaWRlciBhIG1ldGFib2xpdGUgYXMgcmVzcG9uc2l2ZSB0byBjZWZwaXJhbWlkZQpjZWZwaXJhbWlkZS56c2NvcmUudGhyZXNob2xkPC1hcy5udW1lcmljKHF1YW50aWxlKGFicyh6YW1waWVyaS5tZXRhYm9saWMucHJvZmlsZXNbLCJDZWZwaXJhbWlkZSJdKSwwLjksbmEucm0gPSBUKSkKI2RlZmluZSBtZXRhYm9saXRlcyB3aG9zZSBjb25jZW50cmF0aW9uIHdhcyBhbHRlcmVkIGJ5IGNlZnBpcmFtaWRlCmNlZnBpcmFtaWRlLnRyZWF0bWVudC5kaWZmZXJlbnRpYWwubWV0YWJvbGl0ZXM8LXphbXBpZXJpLm1ldGFib2xpYy5wcm9maWxlc1t3aGljaChhYnMoemFtcGllcmkubWV0YWJvbGljLnByb2ZpbGVzWywiQ2VmcGlyYW1pZGUiXSk+PSBjZWZwaXJhbWlkZS56c2NvcmUudGhyZXNob2xkKSwiTWV0YWJvbGl0ZV9pZHMiXQojcmVtb3ZlIGR1cGxpY2F0aW9uCmNlZnBpcmFtaWRlLnRyZWF0bWVudC5kaWZmZXJlbnRpYWwubWV0YWJvbGl0ZXM8LXVuaXF1ZShjZWZwaXJhbWlkZS50cmVhdG1lbnQuZGlmZmVyZW50aWFsLm1ldGFib2xpdGVzKQojcmVtb3ZlIGVtcHR5IGVudHJ5CmNlZnBpcmFtaWRlLnRyZWF0bWVudC5kaWZmZXJlbnRpYWwubWV0YWJvbGl0ZXM8LWFzLnZlY3RvcihjZWZwaXJhbWlkZS50cmVhdG1lbnQuZGlmZmVyZW50aWFsLm1ldGFib2xpdGVzWy00N10pCiNzcGxpdCBlbnRyaWVzIHdpdGggbXVsdGlwbGUgS0VHRyBJRHMKY2VmcGlyYW1pZGUudHJlYXRtZW50LmRpZmZlcmVudGlhbC5tZXRhYm9saXRlczwtc2FwcGx5KDE6bGVuZ3RoKGNlZnBpcmFtaWRlLnRyZWF0bWVudC5kaWZmZXJlbnRpYWwubWV0YWJvbGl0ZXMpLGZ1bmN0aW9uKHgpe3N0cnNwbGl0KGNlZnBpcmFtaWRlLnRyZWF0bWVudC5kaWZmZXJlbnRpYWwubWV0YWJvbGl0ZXNbeF0sc3BsaXQ9In4iKVtbMV1dfSkKI3NhdmUgSURzIG9mIGFsdGVyZWQgbWV0YWJvbGl0ZXMKI3dyaXRlLmNzdihmaWxlPSIuLi9EYXRhL01ldGFib2xpY19wcm9maWxlcy9DYW1wb3NfWmFtcGllcmlfZGF0YS9kaWZmZXJlbnRpYWxfbWV0YWJvbGl0ZXNfY2VmcGlyYW1pZGVfcmVsYXRlZF8wODMwMjAyMi5jc3YiLGFycmF5KGFzLmNoYXJhY3Rlcih1bmxpc3QoY2VmcGlyYW1pZGUudHJlYXRtZW50LmRpZmZlcmVudGlhbC5tZXRhYm9saXRlcykpKSkKI3BlcmZvcm0gZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gYW5hbHlzaXMgb2YgYXJjQSBLTyB0cmFuc2NyaXB0aW9uYWwgZGF0YSBmcm9tIFBhcmsgZXQgYWwuIDIwMTMgKFBMb1MgR2VuZXRpY3MpCiNyZWFkIG5vcm1hbGl6ZWQgR0VPIGRhdGEgKGFjY2Vzc2lvbiBJRDogR1NFNDY0MTUpCmFyY0Eua28ucGFyay50cmFuc2NyaXB0b21lczwtcmVhZC5jc3YoIi4uL0RhdGEvRGlmZmVyZW50aWFsX2V4cHJlc3Npb25fYW5hbHlzaXMvR0VPX1BhcmsyMDEzL2FyY0Ffa29fdHJhbnNjcmlwdG9taWNzX1BhcmsgZXQgYWxfMjAxMy5jc3YiLGhlYWRlcj1ULHJvdy5uYW1lcyA9IDEpCiN1cGRhdGUgcm93IG5hbWVzIHdpdGggbG9jdXMgdGFnCnJvd25hbWVzKGFyY0Eua28ucGFyay50cmFuc2NyaXB0b21lcyk8LXNhcHBseSgxOm5yb3coYXJjQS5rby5wYXJrLnRyYW5zY3JpcHRvbWVzKSxmdW5jdGlvbih4KXtzdHJzcGxpdChyb3duYW1lcyhhcmNBLmtvLnBhcmsudHJhbnNjcmlwdG9tZXMpW3hdLHNwbGl0ID0gIjA3MTAiKVtbMV1dWzFdfSkKI2xvZzIgdHJhbnNmb3JtIHRoZSB2YWx1ZXMKYXJjQS5rby5wYXJrLnRyYW5zY3JpcHRvbWVzPC1sb2cyKGFyY0Eua28ucGFyay50cmFuc2NyaXB0b21lcykKI3BlcmZvcm0gZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gYW5hbHlzaXMgd2l0aCBCYXllc1QgYXMgYmVmb3JlCmFyY0Eua28ucmVzcG9uc2UucGFyazwtYmF5ZXNUKGFyY0Eua28ucGFyay50cmFuc2NyaXB0b21lcyxudW1DID0gMyxudW1FID0gMyxjb25mID0gNyxkb011bHR0ZXN0ID0gVCkKYXJjQS5rby5kZWdzLnBhcms8LXJvd25hbWVzKGFyY0Eua28ucmVzcG9uc2UucGFyaylbd2hpY2goYXJjQS5rby5yZXNwb25zZS5wYXJrJEJIIDwgMC4wNSAmIGFicyhhcmNBLmtvLnJlc3BvbnNlLnBhcmskbWVhbkMgLSBhcmNBLmtvLnJlc3BvbnNlLnBhcmskbWVhbkUpPjEpXQojc2F2ZSBmaWxlIHdpdGggREVHcwojd3JpdGUuY3N2KGZpbGU9Ii4uL0RhdGEvTWV0YWJvbGljX3Byb2ZpbGVzL0NhbXBvc19aYW1waWVyaV9kYXRhL2FyY0FfS09fREVHc19QYXJrMjAxMy5jc3YiLGFyY0Eua28uZGVncy5wYXJrKQojaWRlbnRpZnkgbWV0YWJvbGl0ZXMgd2hvc2UgY29uY2VudHJhdGlvbiBpcyBhbHRlcmVkIGJ5IHRoZSBkZWxldGlvbiBvZiBhcmNBCiNkYXRhICBzb3VyY2VkIGZyb20gRnVocmVyIGV0IGFsLiAoTW9sZWN1bGFyIFN5c3RlbXMgQmlvbG9neSAyMDE3KQojZGF0YSB3YXMgZG93bmxvYWRlZCBmcm9tIHRoZSBCaW9TdHVkaWVzIGRhdGFiYXNlIChhY2Nlc3Npb24gUy1CU1NUNSkKbmVnYXRpdmUuaW9ucy50by5tZXRhYm9saXRlcy5tYXA8LXJlYWQuY3N2KCIuLi9EYXRhL01ldGFib2xpY19wcm9maWxlcy9GdWhyZXJfWmFtcGllcmlfZXRfYWxfZGF0YS9uZWdfa2VnZ19hbGxfM21ELmNzdiIpCnBvc2l0aXZlLmlvbnMudG8ubWV0YWJvbGl0ZXMubWFwPC1yZWFkLmNzdigiLi4vRGF0YS9NZXRhYm9saWNfcHJvZmlsZXMvRnVocmVyX1phbXBpZXJpX2V0X2FsX2RhdGEvcG9zX2tlZ2dfYWxsXzNtRC5jc3YiKQpuZWdhdGl2ZS5pb25zLnpzY29yZXM8LXJlYWQuY3N2KCIuLi9EYXRhL01ldGFib2xpY19wcm9maWxlcy9GdWhyZXJfWmFtcGllcmlfZXRfYWxfZGF0YS9uZWdhdGl2ZV9pb25zX3pzY29yZXNfZ2VuZV9rb3MuY3N2IixoZWFkZXI9VCxyb3cubmFtZXMgPSAxKQpwb3NpdGl2ZS5pb25zLnpzY29yZXM8LXJlYWQuY3N2KCIuLi9EYXRhL01ldGFib2xpY19wcm9maWxlcy9GdWhyZXJfWmFtcGllcmlfZXRfYWxfZGF0YS9wb3NpdGl2ZV9pb25zX3pzY29yZXNfZ2VuZV9rb3MuY3N2IixoZWFkZXI9VCxyb3cubmFtZXMgPSAxKQojY29tYmluZSBhbGwgei1zY29yZXMgaW4gYSBzaW5nbGUgbWF0cml4CmFsbC5pb25zLnpzY29yZXM8LXJiaW5kKGFzLm1hdHJpeChwb3NpdGl2ZS5pb25zLnpzY29yZXMpLGFzLm1hdHJpeChuZWdhdGl2ZS5pb25zLnpzY29yZXMpKQojZGVmaW5lIHRocmVzaG9sZCBmb3IgdG9wIDEwJSBhYnNvbHV0ZSB6LXNjb3JlcyBmb3IgYXJjQSBLTwphcmNBLnpzY29yZS50aHJlc2hvbGQ8LWFzLm51bWVyaWMocXVhbnRpbGUoYWJzKGFsbC5pb25zLnpzY29yZXNbLCJhcmNBIl0pLDAuOSkpCiNkZWZpbmUgdmVjdG9ycyB3aXRoIGFyY0EgS08gei1zY29yZXMKYXJjQS5wb3NpdGl2ZS5pb25zLnpzY29yZXM8LXBvc2l0aXZlLmlvbnMuenNjb3Jlc1ssImFyY0EiXQphcmNBLm5lZ2F0aXZlLmlvbnMuenNjb3JlczwtbmVnYXRpdmUuaW9ucy56c2NvcmVzWywiYXJjQSJdCiNpZGVudGlmeSBkZWNyZWFzZWQgbWV0YWJvbGl0ZXMgYXNzb2NpYXRlZCB3aXRoICgrKSBpb25zCmFyY0EucG9zaXRpdmUuaW9ucy5kZWNyZWFzZWQ8LXdoaWNoKGFyY0EucG9zaXRpdmUuaW9ucy56c2NvcmVzIDw9IC0xKiBhcmNBLnpzY29yZS50aHJlc2hvbGQpCiNtYXAgYWx0ZXJlZCBtZXRhYm9saXRlcyB0byB0aGVpciBLRUdHIGlkcwphcmNBLnBvc2l0aXZlLmlvbnMuZGVjcmVhc2VkLmtlZ2c8LXBvc2l0aXZlLmlvbnMudG8ubWV0YWJvbGl0ZXMubWFwW3doaWNoKHBvc2l0aXZlLmlvbnMudG8ubWV0YWJvbGl0ZXMubWFwWywiaW9uIl0gJWluJSBhcmNBLnBvc2l0aXZlLmlvbnMuZGVjcmVhc2VkKSwiaWQiXQojaWRlbnRpZnkgZGVjcmVhc2VkIG1ldGFib2xpdGVzIGFzc29jaWF0ZWQgd2l0aCAoLSkgaW9ucwphcmNBLm5lZ2F0aXZlLmlvbnMuZGVjcmVhc2VkPC13aGljaChhcmNBLm5lZ2F0aXZlLmlvbnMuenNjb3JlcyA8PSAtMSogYXJjQS56c2NvcmUudGhyZXNob2xkKQojbWFwIGFsdGVyZWQgbWV0YWJvbGl0ZXMgdG8gdGhlaXIgS0VHRyBpZHMKYXJjQS5uZWdhdGl2ZS5pb25zLmRlY3JlYXNlZC5rZWdnPC1uZWdhdGl2ZS5pb25zLnRvLm1ldGFib2xpdGVzLm1hcFt3aGljaChuZWdhdGl2ZS5pb25zLnRvLm1ldGFib2xpdGVzLm1hcFssImlvbiJdICVpbiUgYXJjQS5uZWdhdGl2ZS5pb25zLmRlY3JlYXNlZCksImlkIl0KI2NvbWJpbmUgYWxsIEtFR0cgaWRzCmFyY0EuZGVjcmVhc2VkLm1ldGFib2xpdGVzPC11bmlvbihhcmNBLnBvc2l0aXZlLmlvbnMuZGVjcmVhc2VkLmtlZ2csYXJjQS5uZWdhdGl2ZS5pb25zLmRlY3JlYXNlZC5rZWdnKQojaWRlbnRpZnkgaW5jcmVhc2VkIG1ldGFib2xpdGVzIGFzc29jaWF0ZWQgd2l0aCAoKykgaW9ucwphcmNBLnBvc2l0aXZlLmlvbnMuaW5jcmVhc2VkPC13aGljaChhcmNBLnBvc2l0aXZlLmlvbnMuenNjb3JlcyA+PSBhcmNBLnpzY29yZS50aHJlc2hvbGQpCiNtYXAgYWx0ZXJlZCBtZXRhYm9saXRlcyB0byB0aGVpciBLRUdHIGlkcwphcmNBLnBvc2l0aXZlLmlvbnMuaW5jcmVhc2VkLmtlZ2c8LXBvc2l0aXZlLmlvbnMudG8ubWV0YWJvbGl0ZXMubWFwW3doaWNoKHBvc2l0aXZlLmlvbnMudG8ubWV0YWJvbGl0ZXMubWFwWywiaW9uIl0gJWluJSBhcmNBLnBvc2l0aXZlLmlvbnMuaW5jcmVhc2VkKSwiaWQiXQojaWRlbnRpZnkgaW5jcmVhc2VkIG1ldGFib2xpdGVzIGFzc29jaWF0ZWQgd2l0aCAoLSkgaW9ucwphcmNBLm5lZ2F0aXZlLmlvbnMuaW5jcmVhc2VkPC13aGljaChhcmNBLm5lZ2F0aXZlLmlvbnMuenNjb3JlcyA+PSAgYXJjQS56c2NvcmUudGhyZXNob2xkKQphcmNBLm5lZ2F0aXZlLmlvbnMuaW5jcmVhc2VkLmtlZ2c8LW5lZ2F0aXZlLmlvbnMudG8ubWV0YWJvbGl0ZXMubWFwW3doaWNoKG5lZ2F0aXZlLmlvbnMudG8ubWV0YWJvbGl0ZXMubWFwWywiaW9uIl0gJWluJSBhcmNBLm5lZ2F0aXZlLmlvbnMuaW5jcmVhc2VkKSwiaWQiXQojY29tYmluZSBhbGwgS0VHRyBpZHMKYXJjQS5pbmNyZWFzZWQubWV0YWJvbGl0ZXM8LXVuaW9uKGFyY0EubmVnYXRpdmUuaW9ucy5pbmNyZWFzZWQua2VnZyxhcmNBLnBvc2l0aXZlLmlvbnMuaW5jcmVhc2VkLmtlZ2cpCiNzYXZlIG1ldGFib2xpdGUgaWRzIGluIGEgLmNzdiBmaWxlCiN3cml0ZS5jc3YoZmlsZT0iLi4vRGF0YS9NZXRhYm9saWNfcHJvZmlsZXMvRnVocmVyX1phbXBpZXJpX2V0X2FsX2RhdGEvYXJjQV9rb19kaWZmZXJlbnRpYWxfbWV0YWJvbGl0ZXNfa2VnZ18wODMxMjIuY3N2Iix1bmlvbihhcmNBLmluY3JlYXNlZC5tZXRhYm9saXRlcyxhcmNBLmRlY3JlYXNlZC5tZXRhYm9saXRlcykpCiNnZW5lcmF0ZSBGaWcuIFM3CiNyZWFkIE1ldGFib0FuYWx5c3Qgb3V0cHV0IGZpbGVzCm1ldGFib2FuYWx5c3Qub3V0cHV0LnNlcnRyYWxpbmU8LXJlYWQuY3N2KCIuLi9EYXRhL01ldGFib2xpY19wcm9maWxlcy9DYW1wb3NfWmFtcGllcmlfZGF0YS9NZXRhYm9BbmFseXN0X3NlcnRyYWxpbmVfcGF0aHdheV9yZXN1bHRzXzA4MzAyMDIyLmNzdiIpCm1ldGFib2FuYWx5c3Qub3V0cHV0LmNlZnBpcmFtaWRlPC1yZWFkLmNzdigiLi4vRGF0YS9NZXRhYm9saWNfcHJvZmlsZXMvQ2FtcG9zX1phbXBpZXJpX2RhdGEvTWV0YWJvQW5hbHlzdF9jZWZwaXJhbWlkZV9wYXRod2F5X3Jlc3VsdHNfMDgzMDIwMjIuY3N2IikKbWV0YWJvYW5hbHlzdC5vdXRwdXQuYXJjQS5rbzwtcmVhZC5jc3YoIi4uL0RhdGEvTWV0YWJvbGljX3Byb2ZpbGVzL0Z1aHJlcl9aYW1waWVyaV9ldF9hbF9kYXRhL01ldGFib0FuYWx5c3RfYXJjQV9LT19yZXN1bHRfcGF0aHdheV8wODMxMjIuY3N2IikKI2Nob29zZSBjb2xvciBwYWxldHRlIGZvciBoZWF0bWFwCmhlYXRtYXAuY29sb3JzIDwtIGMoImJsYWNrIiwiZ3JleSIsIndoaXRlIikKI2NyZWF0ZSB0YWJsZXMgd2l0aCBwZXJ0dXJiZWQgcGF0aHdheXMgYmFzZWQgb24gRkRSIHAtdmFsdWVzCnNlcnRyYWxpbmUucGVydHVyYmVkLnBhdGh3YXlzPC1tZXRhYm9hbmFseXN0Lm91dHB1dC5zZXJ0cmFsaW5lW3doaWNoKG1ldGFib2FuYWx5c3Qub3V0cHV0LnNlcnRyYWxpbmVbLCJGRFIiXTw9IDAuMjUpLGMoIlgiLCJGRFIiKV0KY2VmcGlyYW1pZGUucGVydHVyYmVkLnBhdGh3YXlzPC1tZXRhYm9hbmFseXN0Lm91dHB1dC5jZWZwaXJhbWlkZVt3aGljaChtZXRhYm9hbmFseXN0Lm91dHB1dC5jZWZwaXJhbWlkZVssIkZEUiJdPD0gMC4yNSksYygiWCIsIkZEUiIpXQphcmNBLmtvLnBlcnR1cmJlZC5wYXRod2F5czwtbWV0YWJvYW5hbHlzdC5vdXRwdXQuYXJjQS5rb1t3aGljaChtZXRhYm9hbmFseXN0Lm91dHB1dC5hcmNBLmtvWywiRkRSIl08PSAwLjI1KSxjKCJYIiwiRkRSIildCiNjcmVhdGUgdmVjdG9yIHdpdGggYWx0ZXJlZCBtZXRhYm9saWMgcGF0aHdheXMKcGVydHVyYmVkLnBhdGh3YXlzLmNvbWJpbmVkPC11bmlxdWUoYyhhcy5jaGFyYWN0ZXIoc2VydHJhbGluZS5wZXJ0dXJiZWQucGF0aHdheXNbLCJYIl0pLGFzLmNoYXJhY3RlcihjZWZwaXJhbWlkZS5wZXJ0dXJiZWQucGF0aHdheXNbLCJYIl0pLGFzLmNoYXJhY3RlcihhcmNBLmtvLnBlcnR1cmJlZC5wYXRod2F5c1ssIlgiXSkpKQojY3JlYXRlIG1hdHJpeCB3aXRoIHBhdGh3YXlzIGlkZW50aWZpZWQgYXMgcGVydHVyYmVkIGJ5IE1ldGFib0FuYWx5c3QgCnBlcnR1cmJlZC5wYXRod2F5cy5tYXRyaXg8LW1hdHJpeChuY29sPTMsbnJvdz1sZW5ndGgocGVydHVyYmVkLnBhdGh3YXlzLmNvbWJpbmVkKSxkaW1uYW1lcyA9IGxpc3QocGVydHVyYmVkLnBhdGh3YXlzLmNvbWJpbmVkLGMoImFyY0EgS08iLCJTZXJ0cmFsaW5lLXRyZWF0ZWQiLCJDZWZwaXJhbWlkZS10cmVhdGVkIikpLDEpCiNmaWxsIG91dCB0aGUgbWF0cml4CmZvcihwYXRod2F5IGluIHBlcnR1cmJlZC5wYXRod2F5cy5jb21iaW5lZCkKewogIGlmKCBwYXRod2F5ICVpbiUgc2VydHJhbGluZS5wZXJ0dXJiZWQucGF0aHdheXNbLCJYIl0pCiAgewogICAgY3VycmVudC5wYXRod2F5LnBvc2l0aW9uPC13aGljaChzZXJ0cmFsaW5lLnBlcnR1cmJlZC5wYXRod2F5c1ssIlgiXT09cGF0aHdheSkKICAgIHBlcnR1cmJlZC5wYXRod2F5cy5tYXRyaXhbcGF0aHdheSwiU2VydHJhbGluZS10cmVhdGVkIl08LSBzZXJ0cmFsaW5lLnBlcnR1cmJlZC5wYXRod2F5c1tjdXJyZW50LnBhdGh3YXkucG9zaXRpb24sIkZEUiJdCiAgfQogIGlmKCBwYXRod2F5ICVpbiUgY2VmcGlyYW1pZGUucGVydHVyYmVkLnBhdGh3YXlzWywiWCJdKQogIHsKICAgIGN1cnJlbnQucGF0aHdheS5wb3NpdGlvbjwtd2hpY2goY2VmcGlyYW1pZGUucGVydHVyYmVkLnBhdGh3YXlzWywiWCJdPT1wYXRod2F5KQogICAgcGVydHVyYmVkLnBhdGh3YXlzLm1hdHJpeFtwYXRod2F5LCJDZWZwaXJhbWlkZS10cmVhdGVkIl08LSBjZWZwaXJhbWlkZS5wZXJ0dXJiZWQucGF0aHdheXNbY3VycmVudC5wYXRod2F5LnBvc2l0aW9uLCJGRFIiXQogIH0KICBpZiggcGF0aHdheSAlaW4lIGFyY0Eua28ucGVydHVyYmVkLnBhdGh3YXlzWywiWCJdKQogIHsKICAgIGN1cnJlbnQucGF0aHdheS5wb3NpdGlvbjwtd2hpY2goYXJjQS5rby5wZXJ0dXJiZWQucGF0aHdheXNbLCJYIl09PXBhdGh3YXkpCiAgICBwZXJ0dXJiZWQucGF0aHdheXMubWF0cml4W3BhdGh3YXksImFyY0EgS08iXTwtIGFyY0Eua28ucGVydHVyYmVkLnBhdGh3YXlzW2N1cnJlbnQucGF0aHdheS5wb3NpdGlvbiwiRkRSIl0KICB9Cn0KI3Bsb3QgaGVhdG1hcApwaGVhdG1hcCh0KHBlcnR1cmJlZC5wYXRod2F5cy5tYXRyaXgpLGNvbG9yID1oZWF0bWFwLmNvbG9ycyxzY2FsZSA9ICJub25lIixjbHVzdGVyX3Jvd3M9RixjbHVzdGVyX2NvbHMgPSBGLGZvbnRzaXplID0gOCxhbmdsZV9jb2wgPSA5MCwgYnJlYWtzID0gYygwLDAuMSwwLjI1LDEpLG1haW49IkZpZy4gUzciKQpgYGAKNS4zIEZpZy4gNUIKYGBge3J9CiNhc3Nlc3Mgc3VzY2VwdGliaWxpdHkgb2YgdGhlIFdULCBXVCBEYXJjQSwgVGV0UiBhbmQgVGV0UiBEYXJjQSBzdHJhaW5zIHRvIHNlcnRyYWxpbmUgCiNyZWFkIE9EIHJlYWRpbmdzIGZyb20gQmlvc2NyZWVuIGV4cGVyaW1lbnRzIHRvIGdlbmVyYXRlIGNvcnJlc3BvbmRpbmcgZ3Jvd3RoIGN1cnZlcwojZmlyc3QsIHJlYWQgZ3Jvd3RoIGRhdGEgZm9yIFdUIGFuZCBXVCBEYXJjQSB0cmVhdGVkIHdpdGggYSByYW5nZSBvZiBzZXJ0cmFsaW5lIGNvbmNlbnRyYXRpb25zIAojZm9yIGVhY2ggc3RyYWluL3NlcnRyYWxpbmUgY29uY2VudHJhdGlvbiwgdGhlcmUgd2VyZSB0aHJlZSBiaW9sb2dpY2FsIHJlcGxpY2F0ZXMgKGVhY2ggb25lIHdpdGggdGhyZWUgcmVwbGljYXRlcykKI2Jpb3NjcmVlbiBleHBlcmltZW50IHdhcyBwZXJmb3JtZWQgZm9yIGEgdG90YWwgb2YgfjI1aAojV1Qgc3RyYWluIHdhcyBjdWx0dXJlZCBpbiBwbGF0ZSAjIDEgKGllLCB3ZWxscyAjMS0xMDApCiNXVCBEYXJjQSBzdHJhaW4gd2FzIGN1bHR1cmVkIGluIHBsYXRlICMgMiAoaWUsIHdlbGxzICMxMDEtMjAwKQpncm93dGguZGF0YS5XVC5XVGFyY0Euc2VydHJhbGluZTwtcmVhZC5jc3YoIi4uL0RhdGEvU2VydHJhbGluZV9kaWx1dGlvbi9XVF9hbmRfV1QgYXJjQS8yMDIyXzAyMjJfZm9ybWF0dGVkX2RhdGEuY3N2Iixyb3cubmFtZXM9MSkKI25vcm1hbGl6ZSBkYXRhIGJ5IHN1YnRyYWN0aW5nIG1pbmltdW0gT0QgcmVhZGluZyBwZXIgd2VsbCAKI25vcm1hbGl6ZWQgbWF0cml4IGluY2x1ZGVzIHRoZSBmaXJzdCB+MTZoIG9mIGdyb3d0aApncm93dGguZGF0YS5XVC5XVGFyY0Euc2VydHJhbGluZS4xNmgubm9ybWFsaXplZDwtYygpCmZvcihpIGluIDE6bmNvbChncm93dGguZGF0YS5XVC5XVGFyY0Euc2VydHJhbGluZSkpCnsKICBtaW5pbXVtLnJlYWRpbmcuY3VycmVudC53ZWxsPC1taW4oZ3Jvd3RoLmRhdGEuV1QuV1RhcmNBLnNlcnRyYWxpbmVbMTozMyxpXSkKICBncm93dGguZGF0YS5XVC5XVGFyY0Euc2VydHJhbGluZS4xNmgubm9ybWFsaXplZDwtY2JpbmQoZ3Jvd3RoLmRhdGEuV1QuV1RhcmNBLnNlcnRyYWxpbmUuMTZoLm5vcm1hbGl6ZWQsZ3Jvd3RoLmRhdGEuV1QuV1RhcmNBLnNlcnRyYWxpbmVbMTozMyxpXS1taW5pbXVtLnJlYWRpbmcuY3VycmVudC53ZWxsKQp9CiNhZGQgY29sdW1uIG5hbWVzCmNvbG5hbWVzKGdyb3d0aC5kYXRhLldULldUYXJjQS5zZXJ0cmFsaW5lLjE2aC5ub3JtYWxpemVkKTwtY29sbmFtZXMoZ3Jvd3RoLmRhdGEuV1QuV1RhcmNBLnNlcnRyYWxpbmUpCiNkZWZpbmUgbWF4aW11bSBPRCBhbW9uZyBibGFuayB3ZWxscyAod2VsbHMgIyA5Mi0xMDAgd2VyZSBpbmNsdWRlZCBhcyBhIGNvbnRyb2wgZm9yIFdULCBhbmQgd2VsbHMgIyAxOTItMjAwIGFzIGEgY29udHJvbCBmb3IgV1QgYXJjQSkgCiMxc3QgT0QgcmVhZGluZyB3YXMgZXhjbHVkZWQgaW4gdGhpcyBhbmFseXNpcyBiZWNhdXNlIGl0IGNvbW1vbmx5IGdpdmVzIGEgaGlnaGVyIHRoYW4gZXhwZWN0ZWQgcmVhZGluZyAoaWUsIGhpZ2hlciB0aGFuIHRoZSByZWFkaW5nIHRha2VuIGEgZmV3IG1pbnV0ZXMgbGF0ZXIpCnd0Lm1heC5ibGFuazwtbWF4KGdyb3d0aC5kYXRhLldULldUYXJjQS5zZXJ0cmFsaW5lLjE2aC5ub3JtYWxpemVkWy0xLDkyOjEwMF0pCnd0LmFyY0EubWF4LmJsYW5rPC1tYXgoZ3Jvd3RoLmRhdGEuV1QuV1RhcmNBLnNlcnRyYWxpbmUuMTZoLm5vcm1hbGl6ZWRbLTEsMTkyOjIwMF0pCiNkZWZpbmUgd2VsbHMgd2hlcmUgZ3Jvd3RoIHdhcyBvYnNlcnZlZCBhcyB0aG9zZSB3aGVyZSBtYXggT0QgPiAyeCBtYXhpbXVtIGdyb3d0aCBkZXRlY3RlZCBpbiBibGFuayB3ZWxscyAoaW5vY3VsYXRlZCB3aXRoIHN0ZXJpbGUgTEIpCnd0LndlbGxzLnRoYXQuZ3JldzwtbmFtZXMod2hpY2goYXBwbHkoRlVOPW1heCwgTUFSR0lOID0gMixncm93dGguZGF0YS5XVC5XVGFyY0Euc2VydHJhbGluZS4xNmgubm9ybWFsaXplZFstMSwyOjkwXSk+Mip3dC5tYXguYmxhbmspKQp3dC5hcmNBLndlbGxzLnRoYXQuZ3JldzwtbmFtZXMod2hpY2goYXBwbHkoRlVOPW1heCwgTUFSR0lOID0gMixncm93dGguZGF0YS5XVC5XVGFyY0Euc2VydHJhbGluZS4xNmgubm9ybWFsaXplZFstMSwxMDI6MTkwXSk+Mip3dC5hcmNBLm1heC5ibGFuaykpCiNlc3RpbWF0ZSBXVCBNSUMgZm9yIHNlcnRyYWxpbmUKd3Quc2VydHJhbGluZS5jb25jZW50cmF0aW9uczwtcGFzdGUoIldUXyIsYygwLHNlcSgzMCw2MCxieT01KSw4MCksc2VwPSIiKQojZGVmaW5lIGRlZmF1bHQgTUlDIGFzIHRoZSBoaWdoZXN0IGNvbmNlbnRyYXRpb24gdGhhdCB3YXMgdGVzdGVkCnd0LnNlcnRyYWxpbmUubWljPC04MApmb3Iod3QuY29uYyBpbiB3dC5zZXJ0cmFsaW5lLmNvbmNlbnRyYXRpb25zKQp7CnRlbXBvcmFsLmNvbmNlbnRyYXRpb248LWFzLm51bWVyaWMoc3Ryc3BsaXQod3QuY29uYyxzcGxpdD0iXyIpW1sxXV1bMl0pCmlmIChsZW5ndGgoZ3JlcCh3dC5jb25jLHd0LndlbGxzLnRoYXQuZ3JldykpPDIgJiB0ZW1wb3JhbC5jb25jZW50cmF0aW9uIDwgd3Quc2VydHJhbGluZS5taWMpCnsKICB3dC5zZXJ0cmFsaW5lLm1pYzwtdGVtcG9yYWwuY29uY2VudHJhdGlvbgp9Cn0KI2VzdGltYXRlIFdUIERhcmNBIE1JQyBmb3Igc2VydHJhbGluZQp3dC5hcmNBLnNlcnRyYWxpbmUuY29uY2VudHJhdGlvbnM8LXBhc3RlKCJXVGFyY0FfIixjKDAsc2VxKDMwLDYwLGJ5PTUpLDgwKSxzZXA9IiIpICN2YWx1ZXMgaW4gdWcvbWwKI2RlZmF1bHQgTUlDIHZhbHVlCnd0LmFyY0Euc2VydHJhbGluZS5taWM8LTgwCmZvcih3dC5hcmNBLmNvbmMgaW4gd3QuYXJjQS5zZXJ0cmFsaW5lLmNvbmNlbnRyYXRpb25zKQp7CnRlbXBvcmFsLmNvbmNlbnRyYXRpb248LWFzLm51bWVyaWMoc3Ryc3BsaXQod3QuYXJjQS5jb25jLHNwbGl0PSJfIilbWzFdXVsyXSkKaWYgKGxlbmd0aChncmVwKHd0LmFyY0EuY29uYyx3dC5hcmNBLndlbGxzLnRoYXQuZ3JldykpPDIgJiB0ZW1wb3JhbC5jb25jZW50cmF0aW9uIDwgd3QuYXJjQS5zZXJ0cmFsaW5lLm1pYykKewogIHd0LmFyY0Euc2VydHJhbGluZS5taWM8LXRlbXBvcmFsLmNvbmNlbnRyYXRpb24KfQp9CnByaW50KHBhc3RlKCJXVCBTZXJ0cmFsaW5lIE1JQzoiLHd0LnNlcnRyYWxpbmUubWljLCJ1Zy9tbCIsc2VwPSIiKSkKcHJpbnQocGFzdGUoIldUIERhcmNBIFNlcnRyYWxpbmUgTUlDOiIsd3QuYXJjQS5zZXJ0cmFsaW5lLm1pYywidWcvbWwiLHNlcD0iIikpCiNzZWNvbmQsIHJlYWQgZ3Jvd3RoIGRhdGEgZm9yIFRldFIgYW5kIFRldFIgRGFyY0EgdHJlYXRlZCB3aXRoIGRpZmZlcmVudCBzZXJ0cmFsaW5lIGNvbmNlbnRyYXRpb25zIAojZXhwZXJpbWVudCB3YXMgcGVyZm9ybWVkIGZvciBhIHRvdGFsIG9mIH4yNGgKI1RldFIgc3RyYWluIHdhcyBjdWx0dXJlZCBpbiBwbGF0ZSAjIDEgKGllLCB3ZWxscyAjMS0xMDApCiNUZXRSIERhcmNBIHN0cmFpbiB3YXMgY3VsdHVyZWQgaW4gcGxhdGUgIyAyIChpZSwgd2VsbHMgIzEwMS0yMDApCmdyb3d0aC5kYXRhLlRldFIuVGV0UmFyY0Euc2VydHJhbGluZTwtcmVhZC5jc3YoIi4uL0RhdGEvU2VydHJhbGluZV9kaWx1dGlvbi9UZXRSX2FuZF9UZXRSIGFyY0EvMjAyMl8wMjIxX2Zvcm1hdHRlZF9kYXRhLmNzdiIscm93Lm5hbWVzPTEpCiNub3JtYWxpemUgZGF0YSBieSBzdWJ0cmFjdGluZyBtaW5pbXVtIE9EIHJlYWRpbmcgcGVyIHdlbGwKI25vcm1hbGl6ZWQgbWF0cml4IGluY2x1ZGVzIHRoZSBmaXJzdCB+MTZoIG9mIGdyb3d0aApncm93dGguZGF0YS5UZXRSLlRldFJhcmNBLnNlcnRyYWxpbmUuMTZoLm5vcm1hbGl6ZWQ8LWMoKQpmb3IoaSBpbiAxOm5jb2woZ3Jvd3RoLmRhdGEuVGV0Ui5UZXRSYXJjQS5zZXJ0cmFsaW5lKSkKewogIG1pbmltdW0ucmVhZGluZy5jdXJyZW50LndlbGw8LW1pbihncm93dGguZGF0YS5UZXRSLlRldFJhcmNBLnNlcnRyYWxpbmVbMTozMyxpXSkKICBncm93dGguZGF0YS5UZXRSLlRldFJhcmNBLnNlcnRyYWxpbmUuMTZoLm5vcm1hbGl6ZWQ8LWNiaW5kKGdyb3d0aC5kYXRhLlRldFIuVGV0UmFyY0Euc2VydHJhbGluZS4xNmgubm9ybWFsaXplZCwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm93dGguZGF0YS5UZXRSLlRldFJhcmNBLnNlcnRyYWxpbmVbMTozMyxpXS1taW5pbXVtLnJlYWRpbmcuY3VycmVudC53ZWxsKQp9CiNhZGQgY29sdW1uIG5hbWVzCmNvbG5hbWVzKGdyb3d0aC5kYXRhLlRldFIuVGV0UmFyY0Euc2VydHJhbGluZS4xNmgubm9ybWFsaXplZCk8LWNvbG5hbWVzKGdyb3d0aC5kYXRhLlRldFIuVGV0UmFyY0Euc2VydHJhbGluZSkKI2RlZmluZSBtYXhpbXVtIE9EIGFtb25nIGJsYW5rIHdlbGxzICh3ZWxscyAjIDkyLTEwMCB3ZXJlIGluY2x1ZGVkIGFzIGEgY29udHJvbCBmb3IgVGV0UiwgYW5kIHdlbGxzICMgMTkyLTIwMCBhcyBhIGNvbnRyb2wgZm9yIFRldFIgYXJjQSkgCnRldFIubWF4LmJsYW5rPC1tYXgoZ3Jvd3RoLmRhdGEuVGV0Ui5UZXRSYXJjQS5zZXJ0cmFsaW5lLjE2aC5ub3JtYWxpemVkWy0xLDkyOjEwMF0pCnRldFIuYXJjQS5tYXguYmxhbms8LW1heChncm93dGguZGF0YS5UZXRSLlRldFJhcmNBLnNlcnRyYWxpbmUuMTZoLm5vcm1hbGl6ZWRbLTEsMTkyOjIwMF0pCiNkZWZpbmUgd2VsbHMgd2hlcmUgZ3Jvd3RoIHdhcyBvYnNlcnZlZCBhcyB0aG9zZSB3aGVyZSBtYXggT0QgPiAyeCBtYXhpbXVtIGdyb3d0aCBkZXRlY3RlZCBpbiBibGFuayB3ZWxscyAoaW5vY3VsYXRlZCB3aXRoIHN0ZXJpbGUgTEIpCnRldFIud2VsbHMudGhhdC5ncmV3PC1uYW1lcyh3aGljaChhcHBseShGVU49bWF4LCBNQVJHSU4gPSAyLGdyb3d0aC5kYXRhLlRldFIuVGV0UmFyY0Euc2VydHJhbGluZS4xNmgubm9ybWFsaXplZFstMSwyOjkwXSk+Mip0ZXRSLm1heC5ibGFuaykpCnRldFIuYXJjQS53ZWxscy50aGF0LmdyZXc8LW5hbWVzKHdoaWNoKGFwcGx5KEZVTj1tYXgsIE1BUkdJTiA9IDIsZ3Jvd3RoLmRhdGEuVGV0Ui5UZXRSYXJjQS5zZXJ0cmFsaW5lLjE2aC5ub3JtYWxpemVkWy0xLDEwMjoxOTBdKT4yKnRldFIuYXJjQS5tYXguYmxhbmspKQojZXN0aW1hdGUgVGV0UiBNSUMgZm9yIHNlcnRyYWxpbmUKdGV0Ui5zZXJ0cmFsaW5lLmNvbmNlbnRyYXRpb25zPC1wYXN0ZSgiVGV0Ul8iLGMoMCxzZXEoMjAsNTAsYnk9NSksNjApLHNlcD0iIikKI2RlZmF1bHQgdmFsdWUKdGV0Ui5zZXJ0cmFsaW5lLm1pYzwtNjAKZm9yKHRldFIuY29uYyBpbiB0ZXRSLnNlcnRyYWxpbmUuY29uY2VudHJhdGlvbnMpCnsKdGVtcG9yYWwuY29uY2VudHJhdGlvbjwtYXMubnVtZXJpYyhzdHJzcGxpdCh0ZXRSLmNvbmMsc3BsaXQ9Il8iKVtbMV1dWzJdKQppZiAobGVuZ3RoKGdyZXAodGV0Ui5jb25jLHRldFIud2VsbHMudGhhdC5ncmV3KSk8MiAmIHRlbXBvcmFsLmNvbmNlbnRyYXRpb24gPCB0ZXRSLnNlcnRyYWxpbmUubWljKQp7CiAgdGV0Ui5zZXJ0cmFsaW5lLm1pYzwtdGVtcG9yYWwuY29uY2VudHJhdGlvbgp9Cn0KI2RlZmluZSBUZXRSIERhcmNBIE1JQyBmb3Igc2VydHJhbGluZQp0ZXRSLmFyY0Euc2VydHJhbGluZS5jb25jZW50cmF0aW9uczwtcGFzdGUoIlRldFJhcmNBXyIsYygwLDUsc2VxKDEwLDIwLGJ5PTIuNSksMjUsMzApLHNlcD0iIikgI3ZhbHVlcyBpbiB1Zy9tbAojZGVmYXVsdCBNSUMgdmFsdWUKdGV0Ui5hcmNBLnNlcnRyYWxpbmUubWljPC0zMApmb3IodGV0Ui5hcmNBLmNvbmMgaW4gdGV0Ui5hcmNBLnNlcnRyYWxpbmUuY29uY2VudHJhdGlvbnMpCnsKdGVtcG9yYWwuY29uY2VudHJhdGlvbjwtYXMubnVtZXJpYyhzdHJzcGxpdCh0ZXRSLmFyY0EuY29uYyxzcGxpdD0iXyIpW1sxXV1bMl0pCmlmIChsZW5ndGgoZ3JlcCh0ZXRSLmFyY0EuY29uYyx0ZXRSLmFyY0Eud2VsbHMudGhhdC5ncmV3KSk8MiAmIHRlbXBvcmFsLmNvbmNlbnRyYXRpb24gPCB0ZXRSLmFyY0Euc2VydHJhbGluZS5taWMpCnsKICB0ZXRSLmFyY0Euc2VydHJhbGluZS5taWM8LXRlbXBvcmFsLmNvbmNlbnRyYXRpb24KfQp9CnByaW50KHBhc3RlKCJUZXRSIFNlcnRyYWxpbmUgTUlDOiIsdGV0Ui5zZXJ0cmFsaW5lLm1pYywidWcvbWwiLHNlcD0iIikpCnByaW50KHBhc3RlKCJUZXRSIERhcmNBIFNlcnRyYWxpbmUgTUlDOiIsdGV0Ui5hcmNBLnNlcnRyYWxpbmUubWljLCJ1Zy9tbCIsc2VwPSIiKSkKI2NyZWF0ZSBGaWcuIDVCCiNjcmVhdGUgdmVjdG9yIHdpdGggYWxsIHNlcnRyYWxpbmUgY29uY2VudHJhdGlvbnMgKHVnL21sKSB0ZXN0ZWQgYW1vbmcgdGhlIGZvdXIgc3RyYWlucwpzZXJ0cmFsaW5lLmNvbmNlbnRyYXRpb25zPC1jKDAsNSwxMCwxMi41LDE1LDE3LjUsMjAsMjUsMzAsMzUsNDAsNDUsNTAsNTUsNjAsODApCiNkZWZpbmUgZ3Jvd3RoIHBhdHRlcm4gKDE9IGdyb3d0aCwgMD0gbm8gZ3Jvd3RoLCAtMTogbm90IHRlc3RlZCkgb2YgZWFjaCBzdHJhaW4gaW4gdGhlIGZ1bGwgcmFuZ2Ugb2Ygc2VydHJhbGluZSBjb25jZW50cmF0aW9ucyAKdGV0Ui5kb3NlLnJlc3BvbnNlPC1jKDEscmVwKC0xLDUpLHJlcCgxLDMpLHJlcCgwLDQpLC0xLCAwLC0xKQp0ZXRSLmFyY0EuZG9zZS5yZXNwb25zZTwtYyhyZXAoMSw1KSxyZXAoMCw0KSwgcmVwKC0xLDcpKQp3dC5kb3NlLnJlc3BvbnNlPC1jKDEsIHJlcCgtMSw3KSxyZXAoMSwzKSxyZXAoMCw1KSkKd3QuYXJjQS5kb3NlLnJlc3BvbnNlPC0gYygxLCByZXAoLTEsNykscmVwKDEsNCkscmVwKDAsNCkpCiNjcmVhdGUgZG9zZSByZXNwb25zZSBtYXRyaXgKc2VydHJhbGluZS5kb3NlLnJlc3BvbnNlLm1hdHJpeDwtY2JpbmQod3QuZG9zZS5yZXNwb25zZSwgd3QuYXJjQS5kb3NlLnJlc3BvbnNlLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXRSLmRvc2UucmVzcG9uc2UsdGV0Ui5hcmNBLmRvc2UucmVzcG9uc2UpCnJvd25hbWVzKHNlcnRyYWxpbmUuZG9zZS5yZXNwb25zZS5tYXRyaXgpPC1zZXJ0cmFsaW5lLmNvbmNlbnRyYXRpb25zCmNvbG5hbWVzKHNlcnRyYWxpbmUuZG9zZS5yZXNwb25zZS5tYXRyaXgpPC1jKCJXVCIsIldUIGFyY0EiLCAiVGV0UiIsIlRldFIgYXJjQSIpCmhlYXRtYXAuYnJlYWtzPC1jKC0xLC0wLjMzLDAuMzMsMSkKcGhlYXRtYXAoc2VydHJhbGluZS5kb3NlLnJlc3BvbnNlLm1hdHJpeFsxNjoxLF0sc2NhbGU9Im5vbmUiLGNvbG9yPSBjKCJncmV5IiwiI0JFQUVENCIsIiM3RkM5N0YiKSwKICAgICAgICAgY2x1c3Rlcl9yb3dzPUYsY2x1c3Rlcl9jb2xzID0gRixmb250c2l6ZSA9IDExLGFuZ2xlX2NvbCA9IDQ1LCBicmVha3MgPSBoZWF0bWFwLmJyZWFrcywKICAgICAgICAgbGVnZW5kX2JyZWFrcz1oZWF0bWFwLmJyZWFrcyxsZWdlbmQ9VCxtYWluPSJGaWcuIDVCIixhbm5vdGF0aW9uX3JvdyA9ICkKYGBgCjUuNCBDb21wdXRlIEZJQzIgc2NvcmVzIG9mIFdUIGZvciB0aGUgc2VydHJhbGluZS10ZXRyYWN5Y2xpbmUgY29tYmluYXRpb24gCmBgYHtyfQojYW5hbHl6ZSByZXN1bHRzIG9mIERpYU1PTkQgYXNzYXkgZm9yIHRoZSBzZXJ0cmFsaW5lLXRldHJhY3ljbGluZSBjb21iaW5hdGlvbgojZnVuY3Rpb24gdG8gY3JlYXRlIGEgbW9ub3RvbmljYWxseSBkZWNyZWFzaW5nIGRvc2UgcmVzcG9uc2UgY3VydmUgKGFzIGRlc2NyaWJlZCBpbiB0aGUgb3JpZ2luYWwgRGlhTU9ORCBtYW51c2NyaXB0LCBDb2tvbCBldCBhbC4gU2NpZW5jZSBBZHZhbmNlcyAyMDE3KQpjcmVhdGUubW9ub3RvbmljYWxseS5kZWNyZWFzaW5nLnZlY3RvcjwtZnVuY3Rpb24ob2QudmVjdG9yKQp7CiAgb3V0cHV0LnZlY3RvcjwtYyhvZC52ZWN0b3JbMV0pCiAgZm9yKGkgaW4gMjpsZW5ndGgob2QudmVjdG9yKSkKICB7CiAgICBjdXJyZW50LnBvaW50PC1vZC52ZWN0b3JbaV0KICAgIGlmKGN1cnJlbnQucG9pbnQ8PSBvZC52ZWN0b3JbaS0xXSAmIGN1cnJlbnQucG9pbnQgPD0gb3V0cHV0LnZlY3RvcltpLTFdKQogICAgewogICAgICBvdXRwdXQudmVjdG9yPC1jKG91dHB1dC52ZWN0b3IsY3VycmVudC5wb2ludCkKICAgIH0KICAgIGVsc2V7CiAgICAgIG91dHB1dC52ZWN0b3I8LWMob3V0cHV0LnZlY3RvcixvdXRwdXQudmVjdG9yW2ktMV0pCiAgICB9CiAgfQogIG91dHB1dC52ZWN0b3IKfQojZnVuY3Rpb24gdG8gbm9ybWFsaXplIE9EIHZlY3RvciBhdCBhIGdpdmVuIHRpbWUgcG9pbnQgd2l0aCByZXNwZWN0IHRvIGFuIHVudHJlYXRlZCBjb250cm9sIChpbml0aWFsIHBvaW50KQpub3JtYWxpemUudmVjdG9yPC1mdW5jdGlvbihvZC52ZWN0b3IpCnsKICBvdXRwdXQudmVjdG9yPC1vZC52ZWN0b3Ivb2QudmVjdG9yWzFdCiAgb3V0cHV0LnZlY3Rvcgp9CiNmdW5jdGlvbiB0byBpbnRlcnBvbGF0ZSBJQzUwIHZhbHVlcwppbnRlcnBvbGF0ZS5pYzUwPC1mdW5jdGlvbihub3JtYWxpemVkLm9kLnZlY3RvcixhYnguY29uY2VudHJhdGlvbi5yYW5nZSkKewogICNhYnguY29uY2VudHJhdGlvbi5yYW5nZSBpcyB0aGUgc2V0IG9mIGFudGliaW90aWMgY29uY2VudHJhdGlvbnMgYXNzb2NpYXRlZCB3aXRoIHRoZSBkb3NlIHJlc3BvbnNlIHZlY3RvciAoaWUsIHRoZSBub3JtYWxpemVkIG9kIHZlY3RvcikKICAjY29uZmlybSB0aGF0IHRoZSBub3JtYWxpemVkIHZlY3RvciBjb250YWlucyB2YWx1ZXMgYWJvdmUgYW5kIGJlbG93IDAuNSAoaWUsIHRoZSBJQzUwIHBvaW50KQogIHBvc2l0aW9ucy5iZWxvdy5pYzUwPC13aGljaChub3JtYWxpemVkLm9kLnZlY3RvciA8IDAuNSkKICBwb3NpdGlvbnMuYWJvdmUuaWM1MDwtd2hpY2gobm9ybWFsaXplZC5vZC52ZWN0b3IgPiAwLjUpCiAgaWYobGVuZ3RoKHBvc2l0aW9ucy5iZWxvdy5pYzUwKT4wICYgbGVuZ3RoKHBvc2l0aW9ucy5hYm92ZS5pYzUwKT4wKQogIHsKICAgICNzcGxpbmUgZml0dGluZwogICAgdGVtcG9yYWwuc3BsaW5lLmZpdHRpbmc8LXNwbGluZShhYnguY29uY2VudHJhdGlvbi5yYW5nZSwgbm9ybWFsaXplZC5vZC52ZWN0b3IsIG49MTAwMDAwMDApCiAgICAjZXN0aW1hdGUgSUM1MAogICAgZXN0aW1hdGVkLmljNTA8LXRlbXBvcmFsLnNwbGluZS5maXR0aW5nJHhbd2hpY2goYWJzKHRlbXBvcmFsLnNwbGluZS5maXR0aW5nJHktMC41KT09bWluKGFicyh0ZW1wb3JhbC5zcGxpbmUuZml0dGluZyR5LTAuNSkpKV0KICB9CiAgZXN0aW1hdGVkLmljNTAKfQojYW5hbHl6ZSBEaWFNT05EIHJlc3VsdHMgZm9yIFdUIGFuZCBXVCBEYXJjQSBzdHJhaW5zCiNkYXRhIGlzIGluIGEgbWF0cml4IHdpdGggMzg0IGNvbHVtbnMgKGVhY2ggY29sdW1uIGlzIGEgd2VsbCBpbiB0aGUgcGxhdGUpCnd0Lnd0LmFyY0EuYmlvdGVrLmRhdGE8LXJlYWQuY3N2KCIuLi9EYXRhL0RpYU1PTkRfYXNzYXkvU2VydHJhbGluZV9UZXRyYWN5Y2xpbmUvV1RfYW5kX1dUIGFyY0EvMjAyMl8wMjI2X2Zvcm1hdHRlZF9kYXRhLkNTViIscm93Lm5hbWVzPTEpCiNpbiB0aGUgMzg0IHdlbGwgcGxhdGU6CiNyb3dzICMgMS01IHdlcmUgdXNlZCBmb3Igc2VydHJhbGluZSBsaW5lYXIgZGlsdXRpb25zIChpZSwgMHgtMnggYnkgMC4yIGluY3JlbWVudHMpCiNyb3dzICMgNi0xMCB3ZXJlIHVzZWQgZm9yIHRldHJhY3ljbGluZSBsaW5lYXIgZGlsdXRpb25zIChpZSwgMHgtMnggYnkgMC4yIGluY3JlbWVudHMpCiNyb3dzICMgMTEtMTUgd2VyZSB1c2VkIGZvciBzZXJ0cmFsaW5lLXRldHJhY3ljbGluZSBjb21iaW5hdGlvbiBsaW5lYXIgZGlsdXRpb25zIChpZSwgMHgtMnggYnkgMC4yIGluY3JlbWVudHMpCiNjb2x1bW5zICMxIGFuZCAjMjQgd2VyZSBibGFuayAoTEIgb25seSkgCiNjb2x1bW5zICMyLTEyIHdlcmUgaW5vY3VsYXRlZCB3aXRoIFdUIGFuZCBjb2x1bW5zICMgMTMtMjMgd2VyZSBpbm9jdWxhdGVkIHdpdGggV1QgYXJjQSBLTyAKI3JlbW92ZSBjb2x1bW4gd2l0aCB0ZW1wZXJhdHVyZSBkYXRhCnd0Lnd0LmFyY0EuYmlvdGVrLmRhdGE8LXd0Lnd0LmFyY0EuYmlvdGVrLmRhdGFbLC0xXQojZGVmaW5lIGRpZmZlcmVuY2UgaW4gT0QgKGRlbHRhIE9EKSBmb3IgZWFjaCB3ZWxsIGFmdGVyIDE2aCBvZiBncm93dGggKG1heCBPRCAtIG1pbiBPRCkKI3RoZSAxNmggZ3Jvd3RoIHdpbmRvdyB3YXMgZGVmaW5lZCBiYXNlZCBvbiB0aGUgRGlhTU9ORCBwcm90b2NvbCAoQ29rb2wtQ2FrbWFrIGV0IGFsLiBKT1ZFIDIwMTgpCnd0Lnd0LmFyY0EuYmlvdGVrLmRlbHRhLm9kPC1jKCkKZm9yKGMgaW4gMTpuY29sKHd0Lnd0LmFyY0EuYmlvdGVrLmRhdGEpKQp7CiAgd3Qud3QuYXJjQS5iaW90ZWsuZGVsdGEub2Q8LWMod3Qud3QuYXJjQS5iaW90ZWsuZGVsdGEub2QsICAgICAgICAgICAgICAgICAgbWF4KHd0Lnd0LmFyY0EuYmlvdGVrLmRhdGFbMTozMyxjXSktbWluKHd0Lnd0LmFyY0EuYmlvdGVrLmRhdGFbMTozMyxjXSkpCn0KbmFtZXMod3Qud3QuYXJjQS5iaW90ZWsuZGVsdGEub2QpPC1jb2xuYW1lcyh3dC53dC5hcmNBLmJpb3Rlay5kYXRhKQojZXh0cmFjdCBkZWx0YSBPRCB2YWx1ZXMgZm9yIFdUIHN0cmFpbgp3dC5kZWx0YS5vZC5tYXRyaXg8LWMoKQojb25lIHJvdyB3aWxsIGNvcnJlc3BvbmQgdG8gYSBsaW5lYXIgZGlsdXRpb24gKGZyb20gMHggdG8gMnggYnkgMC4yeCBpbmNyZW1lbnRzKQpmb3IobCBpbiBMRVRURVJTWzE6MTVdKQp7CiAgc2VsZWN0ZWQud2VsbHM8LXBhc3RlKGwsMjoxMixzZXA9IiIpCiAgd3QuZGVsdGEub2QubWF0cml4PC1yYmluZCh3dC5kZWx0YS5vZC5tYXRyaXgsd3Qud3QuYXJjQS5iaW90ZWsuZGVsdGEub2Rbc2VsZWN0ZWQud2VsbHNdKQp9CiNjaGVjayBkZWx0YSBPRCBwcm9maWxlIGFuZCBpbnRlcnBvbGF0ZSBJQzUwcwpwYXIobWZyb3c9YygzLDMpKQp3dC5pYzUwLnZlY3RvcjwtYygpCmNvbmNlbnRyYXRpb24ubGluZWFyLnJhbmdlPC1zZXEoMCwyLGJ5PTAuMikKZm9yKHIgaW4gMTpucm93KHd0LmRlbHRhLm9kLm1hdHJpeCkpCnsKICAjZ2VuZXJhdGUgbW9ub3RvbmljYWxseSBkZWNyZWFzaW5nIGRlbHRhIE9EIHZlY3RvcgogIGN1cnJlbnQub2QudmVjdG9yPC1jcmVhdGUubW9ub3RvbmljYWxseS5kZWNyZWFzaW5nLnZlY3Rvcih3dC5kZWx0YS5vZC5tYXRyaXhbcixdKQogICNwbG90IGRlbHRhIE9EIGRhdGEgKGllLCBlZmZlY3Qgb2YgdHJlYXRtZW50IG9uIGdyb3d0aCkKICBpZihyIDw2KQogIHsKICBwbG90KHg9Y29uY2VudHJhdGlvbi5saW5lYXIucmFuZ2UseT1ub3JtYWxpemUudmVjdG9yKGN1cnJlbnQub2QudmVjdG9yKSx0eXBlPSJvIiwKICAgICAgIHhsYWI9IltTZXJ0cmFsaW5lKHggSUM1MCldIix5bGFiPSdOb3JtYWxpemVkIE9EJykKICBhYmxpbmUoaD0wLjUsY29sPSJncmV5IixsdHk9MikKICB9CiAgaWYociA+NSAmIHIgPDExKQogIHsKICAgIHBsb3QoeD1jb25jZW50cmF0aW9uLmxpbmVhci5yYW5nZSx5PW5vcm1hbGl6ZS52ZWN0b3IoY3VycmVudC5vZC52ZWN0b3IpLHR5cGU9Im8iLAogICAgICAgICB4bGFiPSJbVGV0cmFjeWNsaW5lKHggSUM1MCldIix5bGFiPSdOb3JtYWxpemVkIE9EJykKICAgIGFibGluZShoPTAuNSxjb2w9ImdyZXkiLGx0eT0yKQogIH0KICBpZihyID4xMCkKICB7CiAgICBwbG90KHg9Y29uY2VudHJhdGlvbi5saW5lYXIucmFuZ2UseT1ub3JtYWxpemUudmVjdG9yKGN1cnJlbnQub2QudmVjdG9yKSx0eXBlPSJvIiwKICAgICAgICAgeGxhYj0iW1RldHJhY3ljbGluZS1TZXJ0cmFsaW5lKHggSUM1MCldIix5bGFiPSdOb3JtYWxpemVkIE9EJykKICAgIGFibGluZShoPTAuNSxjb2w9ImdyZXkiLGx0eT0yKQogIH0KICAjZGVmaW5lIElDNTAgdXNpbmcgdGhlIGFwcHJveGZ1biBmdW5jdGlvbgogIHRlbXBvcmFsLmFwcHJveC5mdW5jLm91dHB1dDwtYXBwcm94ZnVuKHg9bm9ybWFsaXplLnZlY3RvcihjdXJyZW50Lm9kLnZlY3RvcikseT1jb25jZW50cmF0aW9uLmxpbmVhci5yYW5nZSkKICBpYzUwLmludGVycG9sYXRlZC52YWx1ZTwtdGVtcG9yYWwuYXBwcm94LmZ1bmMub3V0cHV0KDAuNSkKICAjYWRkIGVzdGltYXRlZCBJQzUwIHRvIGZpZ3VyZQogIHBvaW50cyh4PWljNTAuaW50ZXJwb2xhdGVkLnZhbHVlLHk9MC41LGNvbD0icmVkIixwY2g9MikKICAjc2F2ZSBlc3RpbWF0ZWQgSUM1MAogIHd0LmljNTAudmVjdG9yPC1jKHd0LmljNTAudmVjdG9yLHJvdW5kKGljNTAuaW50ZXJwb2xhdGVkLnZhbHVlLGRpZ2l0cz0zKSkKfQojZGVmaW5lIFdUIEZJQzIgZm9yIGVhY2ggYmlvbG9naWNhbCByZXBsaWNhdGUKd3QuZmljPC1jKCkKZm9yKGkgaW4gMTo1KQp7CiAgd3QuZmljPC1jKHd0LmZpYyx3dC5pYzUwLnZlY3RvcltpKzEwXS8oMiood3QuaWM1MC52ZWN0b3JbaV0qd3QuaWM1MC52ZWN0b3JbaSs1XSkvKHd0LmljNTAudmVjdG9yW2ldK3d0LmljNTAudmVjdG9yW2krNV0pKSkKfQpwcmludChwYXN0ZSgiV1QgRklDMjoiLHJvdW5kKGdlb01lYW4od3QuZmljKSxkaWdpdHMgPSAzKSxzZXA9IiIpKQpgYGAKNS41IENvbXB1dGUgRklDMiBzY29yZXMgb2YgV1QgYXJjQSBmb3IgdGhlIHNlcnRyYWxpbmUtdGV0cmFjeWNsaW5lIGNvbWJpbmF0aW9uCmBgYHtyfQojZXh0cmFjdCBkZWx0YSBPRCB2YWx1ZXMgZm9yIHRoZSBXVCBhcmNBIHN0cmFpbgp3dC5hcmNBLmRlbHRhLm9kLm1hdHJpeDwtYygpCmZvcihsIGluIExFVFRFUlNbMToxNV0pCnsKICBzZWxlY3RlZC53ZWxsczwtcGFzdGUobCwxMzoyMyxzZXA9IiIpCiAgd3QuYXJjQS5kZWx0YS5vZC5tYXRyaXg8LXJiaW5kKHd0LmFyY0EuZGVsdGEub2QubWF0cml4LHd0Lnd0LmFyY0EuYmlvdGVrLmRlbHRhLm9kW3NlbGVjdGVkLndlbGxzXSkKfQojY2hlY2sgZGVsdGEgT0QgcHJvZmlsZSBhbmQgaW50ZXJwb2xhdGUgSUM1MHMKcGFyKG1mcm93PWMoMywzKSkKd3QuYXJjQS5pYzUwLnZlY3RvcjwtYygpCmZvcihyIGluIDE6bnJvdyh3dC5hcmNBLmRlbHRhLm9kLm1hdHJpeCkpCnsKICAjZ2VuZXJhdGUgbW9ub3RvbmljYWxseSBkZWNyZWFzaW5nIGRlbHRhIE9EIHZlY3RvcgogIGN1cnJlbnQub2QudmVjdG9yPC1jcmVhdGUubW9ub3RvbmljYWxseS5kZWNyZWFzaW5nLnZlY3Rvcih3dC5hcmNBLmRlbHRhLm9kLm1hdHJpeFtyLF0pCiAgI3Bsb3QgZGVsdGEgT0QgZGF0YQogICBpZihyIDw2KQogIHsKICBwbG90KHg9Y29uY2VudHJhdGlvbi5saW5lYXIucmFuZ2UseT1ub3JtYWxpemUudmVjdG9yKGN1cnJlbnQub2QudmVjdG9yKSx0eXBlPSJvIiwKICAgICAgIHhsYWI9IltTZXJ0cmFsaW5lKHggSUM1MCldIix5bGFiPSdOb3JtYWxpemVkIE9EJykKICBhYmxpbmUoaD0wLjUsY29sPSJyZWQiLGx0eT0yKQogIH0KICBpZihyID41ICYgciA8IDExKQogIHsKICAgIHBsb3QoeD1jb25jZW50cmF0aW9uLmxpbmVhci5yYW5nZSx5PW5vcm1hbGl6ZS52ZWN0b3IoY3VycmVudC5vZC52ZWN0b3IpLHR5cGU9Im8iLAogICAgICAgICB4bGFiPSJbVGV0cmFjeWNsaW5lKHggSUM1MCldIix5bGFiPSdOb3JtYWxpemVkIE9EJykKICAgIGFibGluZShoPTAuNSxjb2w9InJlZCIsbHR5PTIpCiAgfQogIGlmKHI+MTApCiAgewogICAgcGxvdCh4PWNvbmNlbnRyYXRpb24ubGluZWFyLnJhbmdlLHk9bm9ybWFsaXplLnZlY3RvcihjdXJyZW50Lm9kLnZlY3RvciksdHlwZT0ibyIsCiAgICAgICAgIHhsYWI9IltTZXJ0cmFsaW5lLVRldHJhY3ljbGluZSh4IElDNTApXSIseWxhYj0nTm9ybWFsaXplZCBPRCcpCiAgICBhYmxpbmUoaD0wLjUsY29sPSJyZWQiLGx0eT0yKQogIH0KICAjZGVmaW5lIElDNTAgdXNpbmcgdGhlIGFwcHJveGZ1biBmdW5jdGlvbgogIHRlbXBvcmFsLmFwcHJveC5mdW5jPC1hcHByb3hmdW4oeD1ub3JtYWxpemUudmVjdG9yKGN1cnJlbnQub2QudmVjdG9yKSx5PWNvbmNlbnRyYXRpb24ubGluZWFyLnJhbmdlKQogIGljNTAuaW50ZXJwb2xhdGVkLnZhbHVlPC10ZW1wb3JhbC5hcHByb3guZnVuYygwLjUpCiAgI2FkZCBlc3RpbWF0ZWQgSUM1MCB0byBmaWd1cmUKICBwb2ludHMoeD1pYzUwLmludGVycG9sYXRlZC52YWx1ZSx5PTAuNSxjb2w9InJlZCIscGNoPTIpCiAgI3NhdmUgZXN0aW1hdGVkIElDNTAKICB3dC5hcmNBLmljNTAudmVjdG9yPC1jKHd0LmFyY0EuaWM1MC52ZWN0b3Iscm91bmQoaWM1MC5pbnRlcnBvbGF0ZWQudmFsdWUsZGlnaXRzPTMpKQp9CiNjb21wdXRlIEZJQzIgb2YgV1QgYXJjQSByZXBsaWNhdGVzCnd0LmFyY0EuZmljPC1jKCkKZm9yKGkgaW4gMTo1KQp7CiAgd3QuYXJjQS5maWM8LWMod3QuYXJjQS5maWMsd3QuYXJjQS5pYzUwLnZlY3RvcltpKzEwXS8oMiood3QuYXJjQS5pYzUwLnZlY3RvcltpXSp3dC5hcmNBLmljNTAudmVjdG9yW2krNV0pLyh3dC5hcmNBLmljNTAudmVjdG9yW2ldK3d0LmFyY0EuaWM1MC52ZWN0b3JbaSs1XSkpKQp9CnByaW50KHBhc3RlKCJXVCBhcmNBIEZJQzI6Iixyb3VuZChnZW9NZWFuKHd0LmFyY0EuZmljKSxkaWdpdHM9Myksc2VwPSIiKSkKYGBgCjUuNiBDb21wdXRlIEZJQzIgb2YgVGV0UiBhcmNBIGZvciB0aGUgc2VydHJhbGluZS10ZXRyYWN5Y2xpbmUgY29tYmluYXRpb24KYGBge3J9CiNhbmFseXplIERpYU1PTkQgcmVzdWx0cyBvZiB0aGUgVGV0UiBhbmQgVGV0UiBEYXJjQSBzdHJhaW5zCiNkYXRhIGlzIGluIGEgbWF0cml4IHdpdGggMzg0IGNvbHVtbnMgKGVhY2ggY29sdW1uIGlzIGEgd2VsbCBpbiBhIHBsYXRlKQp0ZXRSLnRldFIuYXJjQS5iaW90ZWsuZGF0YTwtcmVhZC5jc3YoIi4uL0RhdGEvRGlhTU9ORF9hc3NheS9TZXJ0cmFsaW5lX1RldHJhY3ljbGluZS9UZXRSX2FuZF9UZXRSIGFyY0EvcnVuMS8yMDIyXzAzMDFfZm9ybWF0dGVkX2RhdGEuQ1NWIixyb3cubmFtZXM9MSkKI2luIHRoZSAzODQgd2VsbCBwbGF0ZToKI3Jvd3MgIyAxLTUgd2VyZSB1c2VkIGZvciBzZXJ0cmFsaW5lIGxpbmVhciBkaWx1dGlvbnMgKGllLCAweC0yeCBieSAwLjIgaW5jcmVtZW50cykKI3Jvd3MgIyA2LTEwIHdlcmUgdXNlZCBmb3IgdGV0cmFjeWNsaW5lIGxpbmVhciBkaWx1dGlvbnMgKGllLCAweC0yeCBieSAwLjIgaW5jcmVtZW50cykKI3Jvd3MgIyAxMS0xNSB3ZXJlIHVzZWQgZm9yIHNlcnRyYWxpbmUtdGV0cmFjeWNsaW5lIGNvbWJpbmF0aW9uIGxpbmVhciBkaWx1dGlvbnMgKGllLCAweC0yeCBieSAwLjIgaW5jcmVtZW50cykKI2NvbHVtbnMgIzEgYW5kICMyNCB3ZXJlIGJsYW5rIChMQiBvbmx5KSAKI2NvbHVtbnMgIzItMTIgd2VyZSBpbm9jdWxhdGVkIHdpdGggVGV0UiBhbmQgY29sdW1ucyAjIDEzLTIzIHdlcmUgaW5vY3VsYXRlZCB3aXRoIFRldFIgYXJjQSBLTyAKI3JlbW92ZSBjb2x1bW4gd2l0aCB0ZW1wZXJhdHVyZSBkYXRhCnRldFIudGV0Ui5hcmNBLmJpb3Rlay5kYXRhPC10ZXRSLnRldFIuYXJjQS5iaW90ZWsuZGF0YVssLTFdCiNkZWZpbmUgZGlmZmVyZW5jZSBpbiBPRCAoZGVsdGEgT0QpIGZvciBlYWNoIHdlbGwgYWZ0ZXIgMTZoIG9mIGdyb3d0aCAobWF4IE9EIC0gbWluIE9EKQojdGhlIDE2aCBncm93dGggd2luZG93IHdhcyBkZWZpbmVkIGJhc2VkIG9uIHRoZSBEaWFNT05EIHByb3RvY29sIChDb2tvbC1DYWttYWsgZXQgYWwuIEpPVkUgMjAxOCkKdGV0Ui50ZXRSLmFyY0EuZGVsdGEub2Q8LWMoKQpmb3IoYyBpbiAxOm5jb2wodGV0Ui50ZXRSLmFyY0EuYmlvdGVrLmRhdGEpKQp7CiAgdGV0Ui50ZXRSLmFyY0EuZGVsdGEub2Q8LWModGV0Ui50ZXRSLmFyY0EuZGVsdGEub2QsICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heCh0ZXRSLnRldFIuYXJjQS5iaW90ZWsuZGF0YVsxOjMzLGNdKS1taW4odGV0Ui50ZXRSLmFyY0EuYmlvdGVrLmRhdGFbMTozMyxjXSkpCn0KbmFtZXModGV0Ui50ZXRSLmFyY0EuZGVsdGEub2QpPC1jb2xuYW1lcyh0ZXRSLnRldFIuYXJjQS5iaW90ZWsuZGF0YSkKI2V4dHJhY3QgZGVsdGEgT0QgdmFsdWVzIGZvciBUZXRSIGFyY0Egc3RyYWluCnRldFIuYXJjQS5kZWx0YS5vZC5tYXRyaXg8LWMoKQojb25lIHJvdyB3aWxsIGNvcnJlc3BvbmQgdG8gYSBsaW5lYXIgZGlsdXRpb24gKGZyb20gMHggdG8gMnggYnkgMC4yeCBpbmNyZW1lbnRzKQpmb3IobCBpbiBMRVRURVJTWzE6MTVdKQp7CiAgc2VsZWN0ZWQud2VsbHM8LXBhc3RlKGwsMTM6MjMsc2VwPSIiKQogIHRldFIuYXJjQS5kZWx0YS5vZC5tYXRyaXg8LXJiaW5kKHRldFIuYXJjQS5kZWx0YS5vZC5tYXRyaXgsdGV0Ui50ZXRSLmFyY0EuZGVsdGEub2Rbc2VsZWN0ZWQud2VsbHNdKQp9CiNjaGVjayBkZWx0YSBPRCBwcm9maWxlIGFuZCBpbnRlcnBvbGF0ZSBJQzUwcwpwYXIobWZyb3c9YygzLDMpKQp0ZXRSLmFyY0EuaWM1MC52ZWN0b3I8LWMoKQpmb3IociBpbiAxOm5yb3codGV0Ui5hcmNBLmRlbHRhLm9kLm1hdHJpeCkpCnsKICAjZ2VuZXJhdGUgbW9ub3RvbmljYWxseSBkZWNyZWFzaW5nIGRlbHRhIE9EIHZlY3RvcgogIGN1cnJlbnQub2QudmVjdG9yPC1jcmVhdGUubW9ub3RvbmljYWxseS5kZWNyZWFzaW5nLnZlY3Rvcih0ZXRSLmFyY0EuZGVsdGEub2QubWF0cml4W3IsXSkKICBpZihyPDYpCiAgewogIHBsb3QoeD1jb25jZW50cmF0aW9uLmxpbmVhci5yYW5nZSx5PW5vcm1hbGl6ZS52ZWN0b3IoY3VycmVudC5vZC52ZWN0b3IpLHR5cGU9Im8iLAogICAgICAgeGxhYj0iW1NlcnRyYWxpbmUoeCBJQzUwKV0iLHlsYWI9J05vcm1hbGl6ZWQgT0QnKQogIGFibGluZShoPTAuNSxjb2w9InJlZCIsbHR5PTIpCiAgfQogIGlmKHI+NSAmIHI8MTEpCiAgewogICAgcGxvdCh4PWNvbmNlbnRyYXRpb24ubGluZWFyLnJhbmdlLHk9bm9ybWFsaXplLnZlY3RvcihjdXJyZW50Lm9kLnZlY3RvciksdHlwZT0ibyIsCiAgICAgICAgIHhsYWI9IltUZXRyYWN5Y2xpbmUoeCBJQzUwKV0iLHlsYWI9J05vcm1hbGl6ZWQgT0QnKQogICAgYWJsaW5lKGg9MC41LGNvbD0icmVkIixsdHk9MikKICB9CiAgaWYocj4xMCkKICB7CiAgICBwbG90KHg9Y29uY2VudHJhdGlvbi5saW5lYXIucmFuZ2UseT1ub3JtYWxpemUudmVjdG9yKGN1cnJlbnQub2QudmVjdG9yKSx0eXBlPSJvIiwKICAgICAgICAgeGxhYj0iW1NlcnRyYWxpbmUtVGV0cmFjeWNsaW5lKHggSUM1MCldIix5bGFiPSdOb3JtYWxpemVkIE9EJykKICAgIGFibGluZShoPTAuNSxjb2w9InJlZCIsbHR5PTIpCiAgfQogICNkZWZpbmUgSUM1MCB1c2luZyB0aGUgYXBwcm94ZnVuIGZ1bmN0aW9uCiAgdGVtcG9yYWwuYXBwcm94LmZ1bmM8LWFwcHJveGZ1bih4PW5vcm1hbGl6ZS52ZWN0b3IoY3VycmVudC5vZC52ZWN0b3IpLHk9Y29uY2VudHJhdGlvbi5saW5lYXIucmFuZ2UpCiAgaWM1MC5pbnRlcnBvbGF0ZWQudmFsdWU8LXRlbXBvcmFsLmFwcHJveC5mdW5jKDAuNSkKICAjYWRkIGVzdGltYXRlZCBJQzUwIHRvIGZpZ3VyZQogIHBvaW50cyh4PWljNTAuaW50ZXJwb2xhdGVkLnZhbHVlLHk9MC41LGNvbD0icmVkIixwY2g9MikKICAjc2F2ZSBlc3RpbWF0ZWQgSUM1MAogIHRldFIuYXJjQS5pYzUwLnZlY3RvcjwtYyh0ZXRSLmFyY0EuaWM1MC52ZWN0b3Iscm91bmQoaWM1MC5pbnRlcnBvbGF0ZWQudmFsdWUsZGlnaXRzPTMpKQp9CiNkZWZpbmUgRklDMiBmb3IgVGV0UiBhcmNBIHJlcGxpY2F0ZXMKdGV0Ui5hcmNBLmZpYzwtYygpCmZvcihpIGluIDE6NSkKewogIHRldFIuYXJjQS5maWM8LWModGV0Ui5hcmNBLmZpYyx0ZXRSLmFyY0EuaWM1MC52ZWN0b3JbaSsxMF0vKDIqKHRldFIuYXJjQS5pYzUwLnZlY3RvcltpXSp0ZXRSLmFyY0EuaWM1MC52ZWN0b3JbaSs1XSkvKHRldFIuYXJjQS5pYzUwLnZlY3RvcltpXSt0ZXRSLmFyY0EuaWM1MC52ZWN0b3JbaSs1XSkpKQp9CnByaW50KHBhc3RlKCJUZXRSIGFyY0EgRklDMjoiLHJvdW5kKGdlb01lYW4odGV0Ui5hcmNBLmZpYyksZGlnaXRzPTMpLHNlcD0iIikpCmBgYAo1LjcgQ29tcHV0ZSBGSUMyIG9mIFRldFIgCmBgYHtyfQojZXh0cmFjdCBkZWx0YSBPRCB2YWx1ZXMgZm9yIFRldFIgc3RyYWluCiNOT1RFOnJlcGxpY2F0ZXMgd2l0aCBtb3JlIHRoYW4gb25lIHBvdGVudGlhbCBJQzUwIChvbiB0aGUgcmF3IGRhdGEpIG9yIGluY3JlYXNlZCBncm93dGggYWZ0ZXIgcG90ZW50aWFsIElDNTAgd2VyZSBub3QgdXNlZCBmb3IgRklDMiBjYWxjdWxhdGlvbgp0ZXRSLmRlbHRhLm9kLm1hdHJpeDwtYygpCmZvcihsIGluIExFVFRFUlNbMToxNV0pCnsKICBzZWxlY3RlZC53ZWxsczwtcGFzdGUobCwyOjEyLHNlcD0iIikKICB0ZXRSLmRlbHRhLm9kLm1hdHJpeDwtcmJpbmQodGV0Ui5kZWx0YS5vZC5tYXRyaXgsdGV0Ui50ZXRSLmFyY0EuZGVsdGEub2Rbc2VsZWN0ZWQud2VsbHNdKQp9CiNjaGVjayBkZWx0YSBPRCBwcm9maWxlIGFuZCBpbnRlcnBvbGF0ZSBJQzUwcwpwYXIobWZyb3c9YygzLDMpKQp0ZXRSLmljNTAudmVjdG9yPC1jKCkKZm9yKHIgaW4gMTpucm93KHRldFIuZGVsdGEub2QubWF0cml4KSkKewogICNnZW5lcmF0ZSBtb25vdG9uaWNhbGx5IGRlY3JlYXNpbmcgZGVsdGEgT0QgdmVjdG9yCiAgY3VycmVudC5vZC52ZWN0b3I8LWNyZWF0ZS5tb25vdG9uaWNhbGx5LmRlY3JlYXNpbmcudmVjdG9yKHRldFIuZGVsdGEub2QubWF0cml4W3IsXSkKICAjd2UgZmlyc3QgcGxvdCB0aGUgcmF3IGRvc2UtcmVzcG9uc2UgY3VydmUgKGJsYWNrIGxpbmUpCiAgaWYocjw2KQogIHsKICAgIHBsb3QoeD1jb25jZW50cmF0aW9uLmxpbmVhci5yYW5nZSx5PW5vcm1hbGl6ZS52ZWN0b3IodGV0Ui5kZWx0YS5vZC5tYXRyaXhbcixdKSx0eXBlPSJsIiwgeGxhYj0iW1NlcnRyYWxpbmUoeCBJQzUwKV0iLHlsYWI9J05vcm1hbGl6ZWQgT0QnLG1haW49IkV4cHQxIikKICAgIGFibGluZShoPTAuNSxjb2w9InJlZCIsbHR5PTIpCiAgfQogIGlmKHI+NSAmIHI8MTEpCiAgewogICAgcGxvdCh4PWNvbmNlbnRyYXRpb24ubGluZWFyLnJhbmdlLHk9bm9ybWFsaXplLnZlY3Rvcih0ZXRSLmRlbHRhLm9kLm1hdHJpeFtyLF0pLHR5cGU9ImwiLHhsYWI9IltUZXRyYWN5Y2xpbmUoeCBJQzUwKV0iLHlsYWI9J05vcm1hbGl6ZWQgT0QnLG1haW49IkV4cHQxIikKICAgIGFibGluZShoPTAuNSxjb2w9InJlZCIsbHR5PTIpCiAgfQogIGlmKHI+MTApCiAgewogICAgcGxvdCh4PWNvbmNlbnRyYXRpb24ubGluZWFyLnJhbmdlLHk9bm9ybWFsaXplLnZlY3Rvcih0ZXRSLmRlbHRhLm9kLm1hdHJpeFtyLF0pLHR5cGU9ImwiLCB4bGFiPSJbU2VydHJhbGluZS1UZXRyYWN5Y2xpbmUoeCBJQzUwKV0iLHlsYWI9J05vcm1hbGl6ZWQgT0QnLG1haW49IkV4cHQxIikKICAgIGFibGluZShoPTAuNSxjb2w9InJlZCIsbHR5PTIpCiAgfQogICNhbHNvIHBsb3QgbW9ub3RvbmljYWxseSBkZWNyZWFzaW5nIGRvc2UgcmVzcG9uc2UgY3VydmUgKG9yYW5nZSBsaW5lKQogIHBvaW50cyh4PWNvbmNlbnRyYXRpb24ubGluZWFyLnJhbmdlLHk9bm9ybWFsaXplLnZlY3RvcihjdXJyZW50Lm9kLnZlY3RvciksdHlwZT0ibyIsY29sPSJvcmFuZ2UiKQogICNkZWZpbmUgSUM1MCB1c2luZyB0aGUgaW4taG91c2Ugc3BsaW5lIGZpdHRpbmcgZnVuY3Rpb24gKG1vcmUgYWNjdXJhdGUgdGhhbiBhcHByb3hmdW4pCiAgaWM1MC5pbnRlcnBvbGF0ZWQudmFsdWU8LWludGVycG9sYXRlLmljNTAobm9ybWFsaXplLnZlY3RvcihjdXJyZW50Lm9kLnZlY3RvciksY29uY2VudHJhdGlvbi5saW5lYXIucmFuZ2UpCiAgI2FkZCBlc3RpbWF0ZWQgSUM1MCB0byBmaWd1cmUKICBwb2ludHMoeD1pYzUwLmludGVycG9sYXRlZC52YWx1ZSx5PTAuNSxjb2w9InJlZCIscGNoPTIpCiAgI3NhdmUgZXN0aW1hdGVkIElDNTAKICB0ZXRSLmljNTAudmVjdG9yPC1jKHRldFIuaWM1MC52ZWN0b3Iscm91bmQoaWM1MC5pbnRlcnBvbGF0ZWQudmFsdWUsZGlnaXRzPTMpKQp9CiNyZXBsaWNhdGVzICMgMSwgIzMgYW5kICM0IG5vdCB1c2VkIGZvciBGSUMyIGVzdGltYXRpb24gYWZ0ZXIgdmlzdWFsIGluc3BlY3Rpb24gb2YgdGhlIHNlcnRyYWxpbmUgZG9zZSByZXNwb25zZSBjdXJ2ZXMgCiNhIHNlY29uZCBleHBlcmltZW50IChiZWxvdykgd2FzIHBlcmZvcm1lZCAgdG8gaW5jcmVhc2UgdGhlIG51bWJlciBvZiBiaW9sb2dpY2FsIHJlcGxpY2F0ZXMKI2RlZmluZSBGSUMyIG9mIFRldFIgcmVwbGljYXRlcyBpbiBleHBlcmltZW50ICMgMQp0ZXRSLmZpYy5leHB0MTwtYygpCmZvcihpIGluIDE6NSkKewogIHRldFIuZmljLmV4cHQxPC1jKHRldFIuZmljLmV4cHQxLHRldFIuaWM1MC52ZWN0b3JbaSsxMF0vKDIqKHRldFIuaWM1MC52ZWN0b3JbaV0qdGV0Ui5pYzUwLnZlY3RvcltpKzVdKS8odGV0Ui5pYzUwLnZlY3RvcltpXSt0ZXRSLmljNTAudmVjdG9yW2krNV0pKSkKfQp0ZXRSLmZpYy5leHB0MTwtdGV0Ui5maWMuZXhwdDFbYygyLDUpXQojcmVhZCBkYXRhIGNvbGxlY3RlZCBvbiBhIHNlY29uZCBEaWFNT05EIGV4cGVyaW1lbnQgZm9yIFRldFIgKGZpdmUgYmlvbG9naWNhbCByZXBsaWNhdGVzKQp0ZXRSLmJpb3Rlay5kYXRhLmV4cHQyPC1yZWFkLmNzdigiLi4vRGF0YS9EaWFNT05EX2Fzc2F5L1NlcnRyYWxpbmVfVGV0cmFjeWNsaW5lL1RldFJfYW5kX1RldFIgYXJjQS9ydW4yLzIwMjJfMDQxM19mb3JtYXR0ZWRfZGF0YS5DU1YiLHJvdy5uYW1lcz0xKQojaW4gdGhlIDM4NCB3ZWxsIHBsYXRlOgojcm93cyAjIDEtNSB3ZXJlIHVzZWQgZm9yIHNlcnRyYWxpbmUgbGluZWFyIGRpbHV0aW9ucyAoMHgsLjJ4LC40eCwuNngsLjh4LDEuMHgsMS4yeCwxLjZ4LDEuNHgsMS44eCwyLjB4KSkKI3Jvd3MgIyA2LTEwIHdlcmUgdXNlZCBmb3IgdGV0cmFjeWNsaW5lIGxpbmVhciBkaWx1dGlvbnMgKGllLCAweC0yeCBieSAwLjIgaW5jcmVtZW50cykKI3Jvd3MgIyAxMS0xNSB3ZXJlIHVzZWQgZm9yIHNlcnRyYWxpbmUtdGV0cmFjeWNsaW5lIGNvbWJpbmF0aW9uIGxpbmVhciBkaWx1dGlvbnMgKGllLCAweC0yeCBieSAwLjIgaW5jcmVtZW50cykKI2NvbHVtbnMgIzEsICMxMy0xNSB3ZXJlIGJsYW5rIChMQiBvbmx5KSAKI2NvbHVtbnMgIzItMTIgd2VyZSBpbm9jdWxhdGVkIHdpdGggVGV0UiAKI3JlbW92ZSBjb2x1bW4gd2l0aCB0ZW1wZXJhdHVyZSBkYXRhCnRldFIuYmlvdGVrLmRhdGEuZXhwdDI8LXRldFIuYmlvdGVrLmRhdGEuZXhwdDJbLC0xXQojZXh0cmFjdCBkZWx0YSBPRCB2YWx1ZXMgCnRldFIuYmlvdGVrLmRlbHRhLm9kLmV4cHQyPC1jKCkKZm9yKGMgaW4gMTpuY29sKHRldFIuYmlvdGVrLmRhdGEuZXhwdDIpKQp7CiAgdGV0Ui5iaW90ZWsuZGVsdGEub2QuZXhwdDI8LWModGV0Ui5iaW90ZWsuZGVsdGEub2QuZXhwdDIsICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4KHRldFIuYmlvdGVrLmRhdGEuZXhwdDJbMTozMyxjXSktbWluKHRldFIuYmlvdGVrLmRhdGEuZXhwdDJbMTozMyxjXSkpCn0KbmFtZXModGV0Ui5iaW90ZWsuZGVsdGEub2QuZXhwdDIpPC1jb2xuYW1lcyh0ZXRSLmJpb3Rlay5kYXRhLmV4cHQyKQojZGVmaW5lIHRldFIgZGVsdGEgT0QgbWF0cml4IChleHB0ICMyKQp0ZXRSLmRlbHRhLm9kLm1hdHJpeC5leHB0MjwtYygpCmZvcihsIGluIExFVFRFUlNbMToxNV0pCnsKICBzZWxlY3RlZC53ZWxsczwtcGFzdGUobCwyOjEyLHNlcD0iIikKICB0ZXRSLmRlbHRhLm9kLm1hdHJpeC5leHB0MjwtcmJpbmQodGV0Ui5kZWx0YS5vZC5tYXRyaXguZXhwdDIsdGV0Ui5iaW90ZWsuZGVsdGEub2QuZXhwdDJbc2VsZWN0ZWQud2VsbHNdKQp9CiNjaGVjayBkZWx0YSBPRCBwcm9maWxlIGFuZCBpbnRlcnBvbGF0ZSBJQzUwcwpwYXIobWZyb3c9YygzLDMpKQp0ZXRSLmljNTAudmVjdG9yLmV4cHQyPC1jKCkKZm9yKHIgaW4gMTpucm93KHRldFIuZGVsdGEub2QubWF0cml4LmV4cHQyKSkKewogICNnZW5lcmF0ZSBtb25vdG9uaWNhbGx5IGRlY3JlYXNpbmcgZGVsdGEgT0QgdmVjdG9yCiAgY3VycmVudC5vZC52ZWN0b3I8LWNyZWF0ZS5tb25vdG9uaWNhbGx5LmRlY3JlYXNpbmcudmVjdG9yKHRldFIuZGVsdGEub2QubWF0cml4LmV4cHQyW3IsXSkKICBpZihyPDYpCiAgewogICAgcGxvdCh4PWNvbmNlbnRyYXRpb24ubGluZWFyLnJhbmdlW2MoMTo3LDksOCwxMDoxMSldLHk9bm9ybWFsaXplLnZlY3Rvcih0ZXRSLmRlbHRhLm9kLm1hdHJpeC5leHB0MltyLGMoMTo3LDksOCwxMDoxMSldKSx0eXBlPSJsIiwKICAgICAgICAgeGxhYj0iW1NlcnRyYWxpbmUoeCBJQzUwKV0iLHlsYWI9J05vcm1hbGl6ZWQgT0QnLG1haW49IkV4cHQyIikKICAgIGFibGluZShoPTAuNSxjb2w9InJlZCIsbHR5PTIpCiAgfQogIGlmKHI+NSAmIHI8MTEpCiAgewogICAgcGxvdCh4PWNvbmNlbnRyYXRpb24ubGluZWFyLnJhbmdlLHk9bm9ybWFsaXplLnZlY3Rvcih0ZXRSLmRlbHRhLm9kLm1hdHJpeC5leHB0MltyLF0pLHR5cGU9ImwiLAogICAgICAgICB4bGFiPSJbVGV0cmFjeWNsaW5lKHggSUM1MCldIix5bGFiPSdOb3JtYWxpemVkIE9EJyxtYWluPSJFeHB0MiIpCiAgICBhYmxpbmUoaD0wLjUsY29sPSJyZWQiLGx0eT0yKQogIH0KICBpZihyPjEwKQogIHsKICAgIHBsb3QoeD1jb25jZW50cmF0aW9uLmxpbmVhci5yYW5nZSx5PW5vcm1hbGl6ZS52ZWN0b3IodGV0Ui5kZWx0YS5vZC5tYXRyaXguZXhwdDJbcixdKSx0eXBlPSJvIiwKICAgICAgICAgeGxhYj0iW1NlcnRyYWxpbmUtVGV0cmFjeWNsaW5lKHggSUM1MCldIix5bGFiPSdOb3JtYWxpemVkIE9EJyxtYWluPSJFeHB0MiIpCiAgICBhYmxpbmUoaD0wLjUsY29sPSJyZWQiLGx0eT0yKQogIH0KICAjYWxzbyBwbG90IG1vbm90b25pY2FsbHkgZGVjcmVhc2luZyB2ZXJzaW9uIG9mIHRoZSBkb3NlIHJlc3BvbnNlCiAgcG9pbnRzKHg9Y29uY2VudHJhdGlvbi5saW5lYXIucmFuZ2UseT1ub3JtYWxpemUudmVjdG9yKGN1cnJlbnQub2QudmVjdG9yKSx0eXBlPSJvIixjb2w9Im9yYW5nZSIpCiAgI2RlZmluZSBJQzUwIHVzaW5nIHRoZSBpbi1ob3VzZSBzcGxpbmUgZml0dGluZyBmdW5jdGlvbgogIGljNTAuaW50ZXJwb2xhdGVkLnZhbHVlPC1pbnRlcnBvbGF0ZS5pYzUwKG5vcm1hbGl6ZS52ZWN0b3IoY3VycmVudC5vZC52ZWN0b3IpLGNvbmNlbnRyYXRpb24ubGluZWFyLnJhbmdlKQogICNhZGQgZXN0aW1hdGVkIElDNTAgdG8gZmlndXJlCiAgcG9pbnRzKHg9aWM1MC5pbnRlcnBvbGF0ZWQudmFsdWUseT0wLjUsY29sPSJyZWQiLHBjaD0yKQogICNzYXZlIGVzdGltYXRlZCBJQzUwCiAgdGV0Ui5pYzUwLnZlY3Rvci5leHB0MjwtYyh0ZXRSLmljNTAudmVjdG9yLmV4cHQyLHJvdW5kKGljNTAuaW50ZXJwb2xhdGVkLnZhbHVlLGRpZ2l0cz0zKSkKfQojZGVmaW5lIEZJQzIgb2YgVGV0UiByZXBsaWNhdGVzIGluIGV4cHQgIyAyCnRldFIuZmljLmV4cHQyPC1jKCkKZm9yKGkgaW4gMTo1KQp7CiAgdGV0Ui5maWMuZXhwdDI8LWModGV0Ui5maWMuZXhwdDIsdGV0Ui5pYzUwLnZlY3Rvci5leHB0MltpKzEwXS8oMioodGV0Ui5pYzUwLnZlY3Rvci5leHB0MltpXSp0ZXRSLmljNTAudmVjdG9yLmV4cHQyW2krNV0pLyh0ZXRSLmljNTAudmVjdG9yLmV4cHQyW2ldK3RldFIuaWM1MC52ZWN0b3IuZXhwdDJbaSs1XSkpKQp9CiNyZW1vdmUgNXRoIHJlcGxpY2F0ZQp0ZXRSLmZpYy5leHB0MjwtdGV0Ui5maWMuZXhwdDJbMTo0XQojY29tYmluZSBUZXRSIEZJQzIgZnJvbSBib3RoIGV4cGVyaW1lbnRzCnRldFIuZmljPC11bmlvbih0ZXRSLmZpYy5leHB0MSx0ZXRSLmZpYy5leHB0MikKcHJpbnQocGFzdGUoIlRldFIgRklDMjoiLHJvdW5kKGdlb01lYW4odGV0Ui5maWMpLGRpZ2l0cz0zKSxzZXA9IiIpKQpgYGAKNS44IEZpZy4gNUMKYGBge3J9CmJveHBsb3Qod3QuZmljLHd0LmFyY0EuZmljLHRldFIuZmljLHRldFIuYXJjQS5maWMsCiAgICAgICAgY29sPXN0cmFpbi5jb2xvcnNbMTo0XSwKICAgICAgICBuYW1lcz1jKCJXVCIsIldUIGFyY0EiLCAiVGV0UiIsIlRldFIgYXJjQSIpLGxhcz0yLAogICAgICAgIGNleC5heGlzPTEuMSxjZXgubGFiPTEuMSx5bGFiPSJGSUMyIix5bGltPWMoMC41LDEuMyksbWFpbj0iRmlnLiA1QyIpCmFibGluZShoPTEsY29sPSJkYXJrZ3JleSIsbHR5PTIpCmBgYA==